various timing attacks and their respective counter-measures.The ECC public key algorithms EC-DH and EC-DSA are subsequently discussed.They’ll make use of the NIST elliptic curves while exploring the ANSI X9.62 and X9.63 standards.The chapter introduces new math in the form of various elliptic curve point multipliers, each with unique performance tradeoffs. The reader is encouraged to read the text “Guide to Elliptic Curve Cryptography” to obtain a deeper understanding of the mathematics behind elliptic curve math.
Q:
When should the development of a threat model begin?A:
Usually alongside the project design itself. However, concerns such as runtime con- straints may not be known in advance, limiting the accuracy of the threat model solu- tions.Q:
Is there any benefit to rolling our own cryptographic algorithms in place of using algo- rithms such as AES or SHA-2?A:
Usually not, as far as security is concerned. It is entirely possible to make a more effi- cient algorithm for a given platform. Such design decisions should be avoided, as they remove the product from the realm of standards compliance and into the skeptic cate-Frequently Asked Questions
The following Frequently Asked Questions, answered by the authors of this book, are designed to both measure your understanding of the concepts presented in this chapter and to assist you with real-life implementation of these concepts. To have your questions about this chapter answered by the author, browse to
Q:
What is certified cryptography? FIPS certification?A:
FIPS certification (see http://csrc.nist.gov/cryptval/) is a process in which a binary or physical implementation of specific algorithms is placed through FIPS licensed validation centers, the result of which is either a pass (and certificate) or failure for specific instance of the implementation.You cannot certify a design or source code.There are various levels of certification depending on how resistant to tampering the product desires to be: level one being a known answer battery, and level four being a physical audit for side channels.Q:
Where can I find the LibTomCrypt and TomsFastMath projects? What platforms do they work with? What is the license?A:
They are hosted at www.libtomcrypt.com.They build with MSVC and the GNU CC compilers, and are supported on all 32- and 64-bit platforms. Both projects are released as public domain and are free for all purposes.ASN.1 Encoding
Solutions in this chapter:
■
Overview of ASN.1
■ASN.1 Syntax
■ASN.1 Data Types
■Implementation
■
Putting It All Together
Chapter 2
21
Summary
Solutions Fast Track
Overview of ASN.1
Abstract Syntax Notation One (ASN.1) is an ITU-T set of standards for encoding and rep- resenting common data types such as printable strings, octet strings, bit strings, integers, and composite sequences of other types as byte arrays in a portable fashion. Simply put, ASN.1 specifies how to encode nontrivial data types in a fashion such that any other platform or third-party tool can interpret the content.
For example, on certain platforms the literal character “a” would be encoded in ASCII (or IA5) as the decimal value 97, whereas on other non-ASCII platforms it may have another encoding. ASN.1 specifies an encoding such that all platforms can decode the string uniformly. Similarly, large integers, bit strings, and dates are also platform sensitive data types that benefit from standardization.
This is beneficial for the developer and for the client (or customer) alike, as it allows the emitted data to be well modeled and interpreted. For example, the developer can tell the client that the data the program they are paying for is in a format another developer down the road can work with—avoiding vendor lock-in problems and building trust.
Formally, the ASN.1 specification we are concerned with is ITU-T X.680, which docu- ments the common data types we will encounter in cryptographic applications. ASN.1 is used in cryptography as it formally specifies the encodings down to the byte level of various data types that are not always inherently portable and, as we will see shortly, encodes them in a deterministic fashion. Being deterministic is particularly important for signature protocols that require a single encoding for any given message to avoid ambiguity.
ASN.1 supports Basic Encoding Rules (BER), Canonical Encoding Rules (CER), and the Distinguished Encoding Rules (DER) (Figure 2.1).These three modes specify how to encode and decode the same ASN.1 types. Where they differ is in the choice of encoding rules. Specifically, as we will see, various parameters such as field length, Boolean representa- tion, and various other parameters can have multiple valid encodings.The DER and CER rules are similar in that they specify fully deterministic encoding rules.That is, where mul- tiple encoding rules are possible only one is actually valid.
Figure 2.1
The Set of ASN.1 Encoding RulesBER
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, andcontainers. 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).
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.
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.
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
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.
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.
Figure 2.2
The ASN.1 Header ByteIn 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 ClassificationsBit 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
8 7 6 5 4 3 2 1
Primitive Type
Constructed Bit
Classification
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 PrimitivesCode 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.
ASN.1 Length Encodings
ASN.1 specifies two methods of encoding lengths depending on the actual length of the ele-