+ All Categories
Home > Documents > An Embedding of Cryptol in HOL-4 - School of...

An Embedding of Cryptol in HOL-4 - School of...

Date post: 18-Mar-2018
Category:
Upload: truonganh
View: 217 times
Download: 4 times
Share this document with a friend
25
An Embedding of Cryptol in HOL-4 Guodong Li and Konrad Slind School of Computing, University of Utah Abstract. In this paper we explore a shallow embedding of Cryptol in HOL-4 by providing a way to import Cryptol programs into HOL-4 so as to support reasoning about concrete Cryptol programs in higher-order logic. Since dealing with the syntax of Cryptol is a straightforward matter of applying well-established parsing technology, we focus on developing mathematical theories to model the semantics of Cryptol among which the sequence concept is the heart. Sequences are modeled as lazy lists/words in HOL-4 successfully, and various sequence operations are defined with useful properties being proven. A model is built to process sequence comprehensions over which sequences could be constructed and iterated. And, concrete cryptographic algorithms including TEA, RC6, MARS and Twofish are implemented in this model, with their functional correctness being verified by simple and effective proof methodology in the course of symbolic evaluation. 1. Introduction As the need for security for hardware and software system keeps growing, integrating cryptographic components into these systems in a fast and correct way has become more attractive. However, the problems of unambiguous specification of cryptographic algorithms and the verification of them are still serious challenges. Currently, most of cryptography algorithms are specified using a mixture of English text and pseudo code, plus a reference implementation written in the C language. Unfortunately, neither English, pseudo code or C code are ideal as a basis for a specification. Firstly, specification in English is often incomplete and/or ambiguous, and there’s no practical way to machine check them. Secondly, the pseudo code is typically a procedural specification that will invariably obscure the underlying mathematics inherent in cryptographic algorithms. Thirdly, using C as the specification language will fact the problem of platform dependence and sequential execution, not to mention the cumber of dealing with memory allocation, pointer manipulation, and so on. Thus, a formal specification language is needed to serve as the basis of a standard library of cryptographic specifications. The nature of cryptography (e.g. information is spread as wide as possible) prohibits applying brute force model checking techniques to verify cryptographic algorithms. To attack the problem of explosion of state space, we’d like to combine model checking techniques with theorems proving techniques in a smart way. Fortunately, cryptographic algorithms behave in a fairly stylized way: there’s a brief initialization phase, followed by a fixed number of rounds each of which performs the same operation, and finally a brief finalization phase. Moreover, the corresponding operations in corresponding phases in encryption and decryption are generally reversible, thus making the proving of reversibility mechanical and fairly suitable for mechanical proving system like HOL-4. For a complex algorithm, we can easily apply brute force verification to the initialization, the finalization and one round of computation. Then we could use induction 1
Transcript

An Embedding of Cryptol in HOL-4

Guodong Li and Konrad Slind

School of Computing, University of Utah

Abstract. In this paper we explore a shallow embedding of Cryptol in HOL-4 by providing a way toimport Cryptol programs into HOL-4 so as to support reasoning about concrete Cryptol programsin higher-order logic. Since dealing with the syntax of Cryptol is a straightforward matter ofapplying well-established parsing technology, we focus on developing mathematical theories tomodel the semantics of Cryptol among which the sequence concept is the heart. Sequences aremodeled as lazy lists/words in HOL-4 successfully, and various sequence operations are definedwith useful properties being proven. A model is built to process sequence comprehensions overwhich sequences could be constructed and iterated. And, concrete cryptographic algorithmsincluding TEA, RC6, MARS and Twofish are implemented in this model, with their functionalcorrectness being verified by simple and effective proof methodology in the course of symbolicevaluation.

1. Introduction

As the need for security for hardware and software system keeps growing, integratingcryptographic components into these systems in a fast and correct way has become moreattractive. However, the problems of unambiguous specification of cryptographic algorithms andthe verification of them are still serious challenges.

Currently, most of cryptography algorithms are specified using a mixture of English text andpseudo code, plus a reference implementation written in the C language. Unfortunately, neitherEnglish, pseudo code or C code are ideal as a basis for a specification. Firstly, specification inEnglish is often incomplete and/or ambiguous, and there’s no practical way to machine checkthem. Secondly, the pseudo code is typically a procedural specification that will invariablyobscure the underlying mathematics inherent in cryptographic algorithms. Thirdly, using C as thespecification language will fact the problem of platform dependence and sequential execution,not to mention the cumber of dealing with memory allocation, pointer manipulation, and so on.Thus, a formal specification language is needed to serve as the basis of a standard library ofcryptographic specifications.

The nature of cryptography (e.g. information is spread as wide as possible) prohibits applyingbrute force model checking techniques to verify cryptographic algorithms. To attack the problemof explosion of state space, we’d like to combine model checking techniques with theoremsproving techniques in a smart way. Fortunately, cryptographic algorithms behave in a fairlystylized way: there’s a brief initialization phase, followed by a fixed number of rounds each ofwhich performs the same operation, and finally a brief finalization phase. Moreover, thecorresponding operations in corresponding phases in encryption and decryption are generallyreversible, thus making the proving of reversibility mechanical and fairly suitable for mechanicalproving system like HOL-4. For a complex algorithm, we can easily apply brute force verificationto the initialization, the finalization and one round of computation. Then we could use induction

1

and composition to combine the verification steps into a verification of the correctness of theentire algorithm.

It turns out that the total number of cryptographic algorithms out in the world is relativelysmall, and will most likely continue to be so. But each algorithm may have multipleimplementations, e.g. for different platforms, and each implementation may have a couple ofmodes to choose. Furthermore, most of the cryptographic algorithms are parameterized such thatthe parameters could be adjusted according to the real situations where the algorithms areapplied. In this respect, the specifications of cryptographic algorithms should be inherentlyportable so that retargeting the deployment platform does not involve recoding the algorithm.And, the code generation process for these algorithms should be authentic. That is, thetranslation from verified source codes to various platforms should not introduced bugs and errors.

To address these challenges, Galois Connections designed a high-level specification languagefor cryptography, Cryptol [1][2], to address challenges of unambiguous specification andverification of cryptographic algorithms, and facilitate the retargeting of cryptographicimplementations to new hardware and software platforms including embedded systems, smartcards, and FPGAs. Cryptol aims to be a domain specific language for cryptography, a platform forvalidation and verification, and a platform for code generation. Cryptol provides goodinvestigation of the characteristics of cryptographic algorithms and systematic support forformalizing them. It also assists the verification of these algorithms by providing methods togenerate test vectors. However, so far there is little support for mechanic verification ofcryptographic algorithms on this system.

As a higher order logic prover, HOL-4 [3] can be used to formalize and verify cryptographicalgorithms and generate executable codes for various platforms. These algorithms are firstspecified unambiguously as functional programs. Then, in the HOL-4 theorem prover, the proofsare proceeded largely by symbolic execution along with applications of algebraic rewrite rules.The proofs could be published along with the specification and codes of the algorithms to provideformal and verified cryptographic algorithms.

In this paper we explore a shallow embedding of Cryptol in HOL-4 by providing a way toimport Cryptol programs into HOL-4 so as to support reasoning about concrete Cryptol programs(thus cryptographic programs in formal form) in higher-order logic. We focus on developingmathematical concepts and theories to model the semantics of Cryptol. The heart of Cryptol,sequences, is modeled successfully by lazy lists in HOL-4.

This paper is organized as follows. In section 2 and section 3 we give brief introduction toCryptol and HOl-4 respectively. Then in section 4 we present the concept of sequence that is theheart of Cryptol, as well as the way how sequences are represented in Cryptol and HOL-4respectively. Sequences are supported in HOL-4 by the llist theory and word theories. We alsodiscuss how to reason about possibly infinite sequences in this section. Then in section 5 weintroduce extended sequence operators borrowed from Cryptol and the modeling of them in HOL-4. And then a concrete example — RC6 — is given to illustrate how to use the sequence supportwe developed to implement cryptographic algorithms in HOL-4 and verify them. Finally we givethe conclusion.

2. Introduction to Cryptol

Cryptol was designed with feedback from expert cryptographers at the National SecurityAgency. It was initially designed to target block symmetric cryptographic algorithms including thefive finalists for the Advanced Encryption Standard (MARS [13], Serpent [15], TwoFish [11], RC6[12], and Rijndael [14]), plus DES. What these algorithms had in common, as well as whatdifferences occurred among them, were identified. Then the idioms and concepts of a domain, aswell as the range of expression that is needed to capture designs were identified. Cryptol ispositioned to become the standard language for cryptography by providing an authoritativereference for validation.

2

As a formal specification language, Cryptol targets to be the basis of a standard library ofcryptographic specifications. Especially, for current and evolving standards, Cryptol hopes toprovide the basis for complete design capture of highly parameterized algorithms that areparameterized on things like block size, key size, number of rounds. In addition, Cryptol is a gooddesign tool for new modes, as well as provide the framework for libraries of modes.

Cryptol provides libraries of Cryptol specifications that are useful for validatingimplementations of crypto algorithms, and it can be used to generate vectors for any sub-part ofan algorithm. The users could perform some machine assisted verification methods like bruteforce verification techniques to subparts of an algorithm to verify partially the correctness of thealgorithms.

Cryptol is also useful as a platform for implementation generation. The most straightforwardis to use Cryptol to generate reference implementations in a variety of industrial languages, suchas Java, or C# for software implementations, or VHDL for hardware. Two main benefits thatCryptol provides for code generation are: Cryptol specifications themselves are inherentlyplatform independent, thus can be easily mapped to the particular requirements of a targetplatform; Cryptol specifications avoid unnecessary sequentiality, thus are well suited for parallelprocessing. For the latter benefit, Cryptol adopts a data-flow method for control flow: the data-dependence instead of the sequential order of the statements in text is analyzed to determinethe execution order of the statements. This declarative approach may help the generation of testvectors for it automatically provides a handle on all the intermediate values.

3. Introduction to HOL-4

HOL is a general purpose proof system for classical, higher order predicate calculus; it hasbeen used to formalize many areas of interest to computer scientists and mathematicians. TheHOL system provides powerful simplifiers, automatic first order provers (both tableaux and modelelimination), a semi-decision procedure for a useful fragment of arithmetic, and a cooperatingdecision procedure mechanism. The HOL System is designed to support interactive theoremproving in higher order logic (hence the acronym `HOL'). To this end, the formal logic isinterfaced to a general purpose programming language (ML, for meta-language) in which termsand theorems of the logic can be denoted, proof strategies expressed and applied, and logicaltheories developed.

The version of higher order logic used in HOL is predicate calculus with terms from the typedlambda calculus (i.e. simple type theory). This was originally developed as a foundation formathematics [17]. The logic has a set theoretic semantics, in which types denote non emptysets and the function space denotes total functions. The logic comprises four components: types,terms, theorems, and theories. A HOL type is either a type variable, or a compound type built byapplying a type operator of arity n to a list (of length n) of types. HOL terms are typed l calculusexpressions. Types and terms form the basis of the prelogic, in which basic algorithmicmanipulations on types and terms are defined: e.g., the free variables of a type or term,substitution, matching, and α and β conversion. These algorithms are used to implement thedeductive system, as well as to implement derived syntax manipulations. In HOL a small set ofvery simple primitive rules and axioms is used as a basis upon which more complex derived rulesmay be built by ML programming. The primitive rules of HOL can be used to build a conventionalnatural deduction system, with introduction and elimination rules for all the standard logicalconnectives. And a HOL theory is a collection of theorems that have been derived from a set ofaxioms in a signature.

There are three main versions of HOL: HOL88, HOL90 and HOL98 (i.e. HOL-4). Each of theseversions is implemented using a different dialect of ML. HOL88 uses Classic ML, HOL90 uses NewJersey Standard ML, and HOL98 uses Moscow ML. The differences between the various versions ofthe HOL system are small.

3

4. Sequence/Stream

Cryptography can be seen as the mathematical manipulation of sequences (or called streams)of data. Up to now, all layers of a cryptographic protocol could be treated uniformly as sequenceprocessing: a computer word is made up of sequences of bits, a block of data is made up ofsequences of words, and a cryptographic algorithm consists of a round stream, with each roundprocesses single or multiple blocks of data. In these algorithms, words, blocks, and streams couldbe all treated as (potentially nested) sequences.

The data in cryptographic algorithms is typically vectors of bits of varying sizes. In blockciphers, the sizes of the vectors usually range from 4 bits upwards to 128 bits, with 8 bit and 32bit being common sizes. Bit vectors are grouped together in various ways (such as a 2D matrix ofbits) to form blocks, where a block is the unit of encryption. To encrypt or decrypt arbitraryamounts of data, a block algorithm is iterated over a stream of blocks using a mode ofoperations.

Sequences are also the basic building blocks of stream ciphers. Compared with block ciphersthat operate on large blocks of bits, stream ciphers typically operate on smaller units ofplaintext, usually bits. Encryption is accomplished by combining the keystream with theplaintext, usually with the bitwise XOR operation. Interestingly, certain modes of operation of ablock cipher effectively transform it into a keystream generator and in this way, any block ciphercan be used as a stream cipher; as in DES in CFB or OFB modes.

4.1 Sequences in Cryptol

Sequences in Cryptol can be either finite, as in a block of words, or infinite, as in arecurrence relation, or stream cipher. In Cryptol, words, blocks, and streams are all treateduniformly as (potentially nested) sequences, thus avoiding the vagaries of platform-dependentword sizes. This approach releases programmers from the burden of care too much about theunderlying architectures. In short, Cryptol uses the simple uniform concept of a sequence toexpress how data is organized in a crypto algorithm. Bit vectors are sequences of bits, matrices,tables and blocks are sequences of sequences, and streams are just sequences of blocks.

Literal sequences in Cryptol are written using brackets surrounding the elements, and spacesseparating them. Sequences are indexed starting with zero, and are written left-to-right inincreasing index order. Bits are written using the constants True and False. Thus, the following isa 7 element sequence of bits:

[True False False True False True True]

Numbers in Cryptol are represented by bit vectors, and, as is typical with crypto algorithms,explicitly use modulus arithmethic, with the modulus based on the size of the vector. Forexample, an 8-bit vector would support arithmetic modulo 28.

In addition to standard arithmetic, Cryptol also supports polynomial arithmetic, which occursin some advanced cryptographic algorithms, such as AES [10] and TwoFish [11]. Addition,multiplication, division, and modulus are all supported over polynomials.

Polynomials are represented as a sequence of the coefficients, with the coefficient for xn

being the nth element of the sequence. Commonly, the coefficients are simply bits. For example,polynomial x7+x5+x+1 is represented as the sequence [True True False False False True False True].

Cryptol is a strongly typed language: every expression and definition must have a valid type,and every value and function must be used in a manner that is consistent with its type. Considerthe sequence

zs = [[0x7a 0x1b] [0x26 0x5c] [0xb4 0x11]]

This is a sequence of 3 elements, each of which is a sequence of 2 elements, each of which isa sequence of 8 bits. We write this in Cryptol as: [3][2][8]Bit. The user may also supply typeannotation zs : [3][2][8] in the definitions.

4

4.2 Modeling Sequences

A list or vector or sequence is essentially a function which takes natural numbers asarguments and returns some value of any type. The function need not be defined for allarguments, but if it is defined for some number then it is also defined for all its predecessors. Sothe function may be defined for all natural numbers and hence is infinite, or it may be definedonly for an initial segment and hence be finite. If the function is defined nowhere, then the list isempty. Sequences could be defined in various ways. In the next section we introduce someformalizations of possibly infinite sequences in several theorem provers based on higher-orderlogic such as HOL (previous version). In this section, we investigate a way to implement bothfinite and infinite sequences that would be adopted in HOL-4.

Finite sequences are normally implemented extensionally: the members are givenextensionally and in their order, and they constitute the successive values of the function whichthe sequence implements. This method is not possible for infinite sequences, so they have to beimplemented intentionally: some function has to be provided that can be used to compute themembers. This will be the case when the function f(n+1) is most readily computed from g(f(n)),where g(x) is particularly efficient to compute. For example, for the powers of 2, [1 2 4 8 …],where the n-th is doubled to give the next power, the doubling function is given to compute thatexponentiation. Similarly, in the sequence of primes [2 3 5 7 11 …] the n-th can be used as astarting point in searching for the next prime. An implementation should provide a function tofind the first of the sequence and a function to compute the rest of the sequence. So betweenthem the first and rest function characterize the sequence.

Thus an infinite sequence consists of a pair of two things: a literal first value, and a functionto compute the rest. The pair is most conveniently constructed from the first value and the nextfunction. For the infinite list of all natural numbers these are 0 and the successor function, forthe list of powers of two they are 1 and the doubling function. However, this method is not theonly one to define sequences. The next section introduces how sequences is modeled in varioushigher order logic theorem provers.

4.3 Related Works

In this section we investigate various ways of formalizing sequences in theorem provers basedon higher-order logic. These ways are adopted in different higher-logic theorem provers:Isabelle/HOL [4], HOL, HOLCF [5] and PVS [6].

Isabelle/HOL is similar to HOL-4. Both of them are based on Church’s formulation of simpletype theory, and are augmented by a ML-style polymorphism and extension mechanisms fordefining new constants and types. In Isabelle/HOL, sequences are defined by mapping the naturalnumbers to options

α seq = N → α option

where α option = NONE | SOME α, and SOME denotes “existing” elements while NONE denotes“nonexisting” elements. For any finite sequence, there exists an i such that

∀k. k<=i ⇒ ∃x. s(k) = SOME x and ∀j. j>i ⇒ s(j) = NONE

Obviously, this i is actually the length of the finite sequence. For any infinite sequence,

∀j. ∃x. s(j) = SOME x

The PVS approach is very close to this one. Note that in this approach it is forbidden thatNONE appears within sequence, thus a normalization action is needed to ensure that eachsequence should be brought into the normal form where no NONE appears within the sequence.This disadvantage brings extra complexity in constructing and manipulating sequences.

In Chou and Peled’s approach [7] that makes use of the lists and functions in the previousversion of HOL, finite sequences comes from lists (which is finite in essence) while infinite

5

sequences is a function mapping natural numbers to elements

α seq = FinSeq (α list) | InfSeq(N → α)

Unfortunately, a couple of operators on sequences have to be implemented separately forfinite sequences and infinite sequences. And, proofs on sequences have to be done on finitesequences and infinite sequences individually.

PVS is a higher order logic prover that features set theoretic semantics. It supports subtyping(where set notation is used to express types) and dependent types (where some components in atype depend on other components in the same type). In PVS, sequences are defined as functionsfrom downward closed subsets of the natural numbers to a data set. For a finite sequence, thedomain of the sequence is the set of the first n natural numbers; for infinite sequences, thedomains of them are the set of natural numbers. The definitions of many operators make nodistinction between finite and infinite sequences. And, no split is needed in reasoningfinite/infinite sequences in many cases, although it is not the case when the appropriate domainsof some functions are needed to derived.

HOLCF extends Isabelle/HOL with concepts of domain theory such as complete partial orders,continuous functions and a fixed point operator. It employs domain theory to extend algebraiclists to infinity, thus finite sequences and infinite sequences are treated in the same way.Sequences are defined by the simple recursive domain equation

domain α Seq = nil | α ∗ (lazy α Seq)

where ∗ is the “cons” operator of the data type. The domain package automatically proves anumber of user-relevant theorems. HOLCF provides a strong structural induction method toreason about infinite sequences in a way similar to reasoning about finite sequences provided thatan admissibility requirement is met. A predicate P is defined to be admissible if it holds for theleast upper bound of every chain satisfying P. And, a syntactic criterion [8] could be used to showthat a predicate is admissible: if P contains no existential quantifier or negation after beingreduced to conjunctive normal form, the continuity of all functions occurring in P implies theadmissibility of P. In addition to this induction method and conventional fixed point induction,HOLCF also provides structural induction rules for finite sequences, plus a take lemma and abisimulation rule as proof principles.

Among above approaches, HOLCF goes furthest in providing powerful formalization plus a setof proof principles. In HOL-4 we provides a way to define sequences corecursively and provides arich set of proof principles that rival with HOLCF.

4.4 Sequences as Lazy Lists in HOL-4

In HOL-4, sequences are implemented as lazy lists in general

α Seq = nil | α ∗ (lazy α Seq)

where ∗ is the “cons” operator of the data type. Literal sequences in HOL-4 are written usingspecial bracket pairs, [| and |], surrounding the elements, and columns separating them. Thus[||] represents an empty lazy list.

Sequences are indexed in the same way as that in Cryptol. For example, the sequence of firstfive primes is [|2; 3; 5; 7; 11|]. Finite sequences are normally implemented extensionally byspecifying the members in their order. However, this method is not possible for infinite sequencesin principle. Fortunately, some infinite sequences with fixed gap between two consecutiveelements could be represented by specifying the first few elements plus a … for the rest. Forinstance, the infinite sequence of odd numbers is [1 3 5 …]. For general infinite sequences, theyhave to be implemented intentionally: some next function has to be provided that can be used tocompute the members. In this case, an implementation should provide a way to find the first ofthe sequence and a function to compute the rest of the sequence. HOL-4 offers a llist theory to

6

assist the definitions of and reasoning about possibly infinite sequences.The theory llist contains the definition of a type of possibly infinite sequences. This type is

similar to the “lazy lists’' of programming languages like Haskell, hence the name of the theory.The llist theory has a number of constants that are analogous to constants in the theory of finitelists. The llist versions of these constants have the same names, but with a capital `L`prepended. Thus, some of the core constants in this theory are

LNIL : 'a llist LCONS : 'a -> 'a llist -> 'a llist LHD : 'a llist -> 'a option LTL : 'a llist -> 'a llist option

The LHD and LTL constants return NONE when applied to the empty sequence, LNIL. This useof an option type is another way of modelling the essential partiality of these constants. (In thetheory of lists, the analogous HD and TL functions simply have unspecified values when applied toempty lists. ). The LCONS is overloaded as ::: in the theory.

Mapping back and forth from lists to lazy lists is accomplished by fromList and toList

fromList [] = LNILfromList (h::t) = h ::: (fromList t)

toList LNIL = SOME []toList (LCONS h t) = OPTION_MAP (CONS h) (toList t)

The type llist is not inductive, and there is no primitive recursion theorem supporting thedefinition of functions that have domains of type llist. Rather, llist is a coinductive type, and hasan axiom that justifies the definition of corecursive functions that defines a llist:

[llist_Axiom] |- ∀f : 'a -> ('a # 'b) option. ∃g : 'a -> 'b llist. (∀x. LHD (g x) = OPTION_MAP SND (f x)) ∧ (∀x. LTL (g x) = OPTION_MAP (g o FST) (f x))

An equivalent form of the above is

[llist_Axiom_1] |- ∀f. ∃g. ∀x. g x = case f x of NONE -> LNIL || SOME (x',y) -> LCONS y (g x')

Given the next function f, either of these two axioms generates the characteristic function gthat represents the sequence. The n+1-th element of the sequence is obtained by applying f onthe n-th element: if f returns NONE, then the sequence terminates and the n+1-th elementdoesn’t exist; otherwise f gives the value of the n+1th element. In practice, llist_Axiom_1 ispreferable for it brings some convenience in proving the properties of the sequence.

The LUNFOLD constant is offered as an alternative of above axioms to define lazy listscoinductively

LUNFOLD = new_specification ("LUNFOLD", ["LUNFOLD"], (SIMP_RULE std_ss [SKOLEM_THM] llist_Axiom_1) )

That is,

|- ∀f' x. LUNFOLD f' x = case f' x of NONE -> [||]

7

|| SOME v -> case v of (v1,v2) -> v2:::LUNFOLD f' v1

Now, lazy lists are defined though instantiating the function f’ (i.e. the next function). Forinstance, the following definition constructs an infinite sequence of consecutive numbers startingfrom any natural number

NumSeq = LUNFOLD (λoldEl. SOME (oldEL + 1,oldEL + 1))

The following property verifies the correctness of this definition:

|- ∀n. NumSeq n = SUC n:::NumSeq (SUC n)

Other constants in the llist theory include LMAP, LFINITE, LNTH, LTAKE, LDROP, and LFILTER. Thefollowing table summarizes the important constants defined in llist theory

Operator Type DescriptionLHD ll a llist -> 'a option If ll is not empty, then return SOME x where x is the first

element of ll; otherwise return NONELTL ll 'a llist -> 'a llist option If ll is not empty, then return SOME x where x is all but

the first element of ll; otherwise return NONELLENGTH ll 'a llist -> num option If ll is finite then return SOME x where x is the number of

elements in ll; otherwise return NONELAPPEND ll1 ll2 'a llist -> 'a list -> 'a list Concatenate ll1 and ll2. If ll1 is infinite, elements of ll2

are inaccessible in the result.LTAKE n ll num -> 'a llist -> 'a list option Take the first n elements of ll. If the number of elements

in ll is less than n, then return NONELDROP n ll num -> 'a llist -> 'a list option Drop the first n elements of ll. If the number of elements

in ll is less than n, then return NONELFILTER P ll ('a -> bool) -> 'a llist -> 'a llist Apply P to each element x of l, from left to right, and

returns the lazy list of those x for which f x evaluated totrue, in the same order as they occurred in the argumentlist

LFINITE ll 'a llist -> bool return true if ll is finite; otherwise return falseLFLATTEN ll 'a llist -> 'a list concatenate the elements of llLL_ALL P ll ('a -> bool) -> ‘b llist -> bool return true if and only if P holds on every element in ll. If

ll is empty, then return true no matter what P isLMAP f ll ('a -> 'b) -> 'a llist -> 'b llist apply f to each element of ll from left to right, returning

the lazy list of results.LNTH num -> 'a llist -> 'a option return the i(th) element of ll, counting from 0

In llist theory the operators are defined corecursively since one cannot define infinite lazylists using well-founded recursion without extensive support to interpret recursion on possiblyinfinite lazy lists. Well-founded recursive function definition packets are provided in some higherorder logic theorem provers [4,5,6] so that functions could be defined conservatively. When usingwell-founded recursion to define a function, the user must supply a well-founded relation on oneof the function’s arguments. But one cannot define infinite lazy lists using well-founded recursionsince the length of an infinite lazy list doesn’t decrease when you take its tail.

Infinite lazy lists and operations over them can be defined corecursively. For instance, LMAPis defined in the llist theory by specifying the next function to be

λll. if ll = [||] then NONE else SOME (THE (LTL ll), f (THE (LHD ll)))

Fortunately, given a corecursive definition, one can prove by coinduction that this definitionsatisfies relevant recursive equations. For example, the function LMAP defined corecursivelysatisfies the following recursive equations

LMAP f [||] = [||] LMAP f (h ::: t) = (f h) ::: (LMAP f t))

8

This property can be proven by coinduction. In [9] a technique is proposed to define functionsthat recursively call themselves an infinite number of times, esp. recursive functions operatingover coinductively-defined types like infinite lazy lists. The basic steps to show that suchdefinitions are well defined are:

1. Express the recursive equations as a fixed point of a function F.2. Show that F maps any two supplied potential solutions to two closer solutions.3. Based on the result of step 2, show that there is a unique solution to the original set of

recursive equations.

Step 2 is the crucial step of this technique. A converging equivalence relation (CER), whichreasons about natural numbers instead of rationals or reals, is proposed to measure the closenessof two solutions. A lazy list CER is constructed for comparing coinductive lists by comparing thefirst i elements of two lazy lists at a given resolution. That is, ll1 is defined to be equivalent toll2 in this relation if and only if

ltake i ll1 = ltake i ll2

where ltake n ll returns a finite lazy list consisting of the first n elements of ll (note that ltakecan be defined by well-founded recursion on a numeric argument ).

This lazy list CER and its derivatives allow recursive definitions of individual lazy lists as wellas recursive definitions of operations over lazy lists. For instance, to define LMAP recursively, wegive the recursion equations for LMAP

LMAP f [||] = [||]LMAP f (h ::: t) = (f x) ::: (LMAP f t)

Then we manage to express the recursive equations as a fixed point of a function F

F LMAP’ = (λll. case ll of [||] ⇒ [||]

| (h ::: t) ⇒ (f h) ::: (LMAP’ t))

Then a unique fixed point of F is proven to exist by showing that F is a contracting functionon the function-space over lazy lists CER. Given the definition of F and basic lemma about ltake,the proof can be done mechanically in two steps in HOL-4.

Although above mechanism isn’t offered by the llist theory in HOL-4 so far, it does illustratesa way to define recursive functions on possibly infinite lazy lists and reason about themmechanically. And, in the llist theory we give theorems for all the important operators of lazylists to show that the coinductive definitions are equivalent to the recursive definitions in somesense. For example, the LMAP theorem corresponds to the recursive definition of LMAP.

LMAP f [||] = [||] LMAP f (h ::: t) = (f h) ::: (LMAP f t))

This applies to other operators as well

LAPPEND [||] x = xLAPPEND (h ::: t) x = h ::: (LAPPEND t x)

LLENGTH [||] = SOME 0LLENGTH (h ::: t) = OPTION_MAP SUC (LLENGTH t)

LFILTER P [||] = [||]LFILTER P (h ::: t) = LFILTER P t, if ¬(P h)LFILTER P (x ::: t) = x ::: (LFILTER P t) if P h

LL_ALL P [||] = trueLL_ALL P (h ::: t) = P h ∧ LL_ALL P t

LNTH n [||] = NONE

9

LNTH 0 (h ::: t) = SOME hLNTH (SUC n) (h:::t) = LNTH n t

LTAKE 0 ll = SOME [||]LTAKE (SUC n) [||] = NONELTAKE (SUC n) (h:::t) = OPTION_MAP (CONS h) (LTAKE n t)

LDROP 0 ll = SOME llLDROP (SUC n) LNIL = NONELDROP (SUC n) (LCONS h t) = LDROP n t

LFLATTEN [||] = [||]LFLATTEN ([||] ::: t) = LFLATTEN tLFLATTEN ((h:::t):::t1) = h ::: (LFLATTEN (t ::: t1))

LFINITE [||] = trueLFINITE (h ::: t) = LFINITE t

Now we give an example to illustrate how to define a function using corecursion and how toreason about it using coinduction. The next function of the infinite sequence of primes [|2; 3; 5;7; 11; …|] is given by

PrimeSeq = LUNFOLD (λll:num llist. SOME (LFILTER (λx. ~(x MOD (THE (LHD ll)) = 0)) ll, THE (LHD ll)))(NumSeq 1)

This definition initially takes an infinite number sequence [|2;3;4;5;…|] as parameter whichthe sifting operation would work on. The head element of this sequence, i.e. 2, is identified asthe first prime. Then, whenever a new prime is identified, all of its multiples are removed fromthe sequence under consideration. Next, the first element of the remaining sequence is the nextnew prime. And then this process is repeated.

First we check the first few elements of this sequence

|- LTAKE 8 PrimeSeq = SOME [2; 3; 5; 7; 11; 13; 17; 19]

Then we show that this sequence is an increasing infinite sequence

|- LLEGNTH PrimeSeq = NONE

|- ∀n. THE (LNTH n PrimeSeq) < THE (LNTH (SUC n) PrimeSeq)

Finally we claim that all elements in this sequence are primes

|- LL_ALL (λp. ~(p = 1) /\ (∀k. (p MOD k = 0) ⇒ (k = 1) \/ (k = p))) PrimeSeq

The last theorem is an instantiation of the following theorem characterizing the LFILTERoperation

|- ∀ll P. LL_ALL P (LFILTER P ll)

In practice, the techniques discussed in section 4.6 are applied to reason about this infiniteprime sequence.

4.5 Bit Sequences as Words in HOL-4

Numbers in Cryptol are represented by bit vectors. In HOL-4, since numbers in cryptographicalgorithms typically involve modulus arithmethic, we would use word-n to represent n-bitnumbers in order to utilize the rich set of word operations provided by HOL-4. For example, an 8-bit word would support arithmetic modulo 28. To justify this representation method, we provideproofs verifying the logical equivalence between n bit words and n bit sequences (which isobvious).

Numbers could be represented by bit sequence, and an n-bit sequence could be written using

10

constants T and F (or 1 and 0). For instance, sequence [|F;T;F;T;T;F;T;F|] represents hexadecimalnumber 0x5A. We could also use sequence [|0;1;0;1;1;0;1;0|] to denote the same number byassigning value 1 to T and 0 to F. Now, this 1/0 bit sequence is equivalent to a word-8 number fora word is a serious of 1/0 bits in essence.

Therefore, numbers in cryptographic algorithms are represented as words in HOL-4. Fornumeral values, the suffix w denotes a word and the prefixes 0x, 0 and 0b denote hexadecimal,octal and binary values. For instance, 10w represents number 10 in word format, and 0x4fw is theordinary number 79 written in hexadecimal word format.

In the word theories, n-bit words are represented as equivalence classes of natural numbers,i.e. sets of numbers equivalent modulo 2n. Each theory instance is for a fixed word size. Wordtheory is built on the bits theory that defines some bit operations over the natural numbers. Mainfunctions in the bits theory -- BITS, SLICE, BIT and BITWISE – are defined using operations fromthe arithmetic theory, esp. DIV, MOD and EXP. The predicates LSB and MSB specialize bit positionszero and len - 1 respectively (where len is number of bits of the word). The function w2n maps aword to a natural number, and the function n2w maps a natural numbers to a word. In the wordtheories, addition, negation (two's complement), subtraction and multiplication are all provided.And six types of shifting are supported: logical shift left, rotate left and four types of shift right.

We provide functions for converting words and fixed length sequences from each other aswell as theorems justify the equivalence of words and fixed length sequences. Mapping back andforth from lists to lazy lists is accomplished by fromWord and toWord

fromWord 0 x = [||]fromWord (SUC n) x = (x DIV 2 ^ n) ::: (fromWord n (x MOD 2 ^ n))

toWord 0 [||] = 0toWord (SUC n) (h ::: t) = h * 2 ^ n + (toWord n t)

Given a bit sequence ll (in which all elements are 0 or 1, i.e. LL_ALL (λel. (el = 0) ∨ (el = 1))ll) of length n, toWord n ll gives the n-bit word corresponding to ll. Given an n-bit word x,fromWord n x gives the corresponding bit sequence that contains n elements.

The invertibility of these two operations is shown by

∀x n. x < 2 ** n ⇒ (toWord n (fromWord n x) = x)

∀ll n. (LLENGTH ll = SOME n) ∧ LL_ALL (λel. (el = 0) ∨ (el = 1)) ll⇒ (fromWord n (toWord n ll) = ll)

Now, it is possible to define a bunch of arithmetic operations on sequences such as shifting,negation, multiplication, etc., by first mapping sequences to the words using toWord and thenconstructing sequences with fromWord (note that the first argument should be assigned the valueof the length of the sequences or the number of bits in a word).

In addition to standard arithmetic, some advanced cryptographic algorithms such as AES andTwoFish also use polynomial arithmetic. And many operations are operations involving the Galoisfield GF(2n). In HOL-4, polynomials over GF(2n) are represented as a sequence of the coefficientsin {0,1}, which in turn is represented by words. Polynomial addition is bitwise exclusive-or ⊕, andso is subtraction. Multiplication is performed modulo an irreducible polynomial of degree n. Forinstance, the polynomial in AES, x8 + x4 + x3 + x + 1, is written as 11B in hexadecimal format. Inorder to multiply a polynomial b(x) by x, i.e., by hex 02, we can left shift (<<) followed by aconditional xor with 11B (which truncates to 1B). This is the xtime operation

xtime b = (b << 1) ⊕ (if b < 80 then 0 else 1B)

With this primitive we can multiply a polynomial by any constant: the operation will bewritten as an infix •. Multiplication with higher powers of x can be achieved by iterating xtimeand intermediate results can be added with ⊕: for example, multiplying 57 by 13 yields

11

57 • 13 = 57 • (01 ⊕ 02 ⊕ 10)

= 57 ⊕ xtime(57) ⊕ xtime4 (57)

= 57 ⊕ AE ⊕ 07= FE

In sum, addition, multiplication, division, and modulus are all supported over polynomialsover GF(2n) in HOL-4.

4.6 Reasoning about Sequences.

In the higher order theorem provers we investigated such as PVS, HOLCF, Isabella HOL andHOL-4, there are three basic proof principles for sequences: point-wise equality, rule usingadmissibility, and bisimulation. Point-wise equality needs to prove equalities of arbitraryfunctions, thus is difficult to accomplish. Rule using admissibility builds on an extensive theoryabout admissibility and continuity of functions. The cost of incorporating this theory into a proverbrings obstacles to the popularity of this principle. The bisimulation principle is easier to use forcoinductive data structures like the lazy lists in HOL-4 where the definitions of sequences and theoperators on sequences exhibit corecursive characterization.

For the infinite case, there are two structural induction rules, namely LFINITE_INDUCTIONand LFINITE_STRONG_INDUCTION, which do not involve admissibility

P [||] ( ∀ t. P t ⇒ ∀h. P (h ::: t))∀ll. LFINITE ll ⇒ P ll

P [||] ( ∀ t. LFINITE t ∧ P t ⇒ ∀h. P (h ::: t))∀ll. LFINITE ll ⇒ P ll

However, there exists on structural induction rule for infinite sequences. For instance, whenP = LFINITE, we couldn’t derive ∀ll. LFINITE ll from premises LFINITE[||] and (∀t. LFINITE t ⇒∀h. LFINITE (h:::t) (which is obviously true). In this case, we provide two important proofprinciples for proving that two llists are equal: the take lemma and bisimulation rule:

∀ n. LTAKE n ll1 = LTAKE n ll2 Ll1 = ll2

∃R. R ll1 ll2 ∧ ∀ ll3 ll4. R ll3 ll4 ⇒ (ll3 = [||] ∧ ll4 = [||]) ∨ (LHD ll3 = LHD ll4) ∧ R (THE (LTL ll3)) (THE(LTL ll4))

Ll1 = ll2

The take lemma states that two sequences are equal if they return the same prefixes oflength n for all possible values of n. This lemma is subsequently used to derive the bisimulationprinciple, which states that two llists ll1 and ll2 are equal if (and only if) it is possible to find arelation R such that R relates the two values, i.e., R ll1 ll2, and if R holds of any two values ll3and ll4, then either both ll3 and ll4 are empty; or the head elements of ll3and ll4 are the same,and the tails of those two values are again related by R.

For example, if we want to use the bisimulation rule to prove that ∀i. LNTH i ll1 = LNTH i ll2⇒ ll1 = ll2, the relation R can be specified as “λll1 ll2. ∀i j. LNTH i ll1 = LNTH i ll2”, then HOL-4’shigh-level simplification tactics allow the proof to be carried out in a few steps by case splitting.

For the situations beyond proving equalities of lazy lists, the proofs go smoothly as well withthe assist of the theorems characterizing the recursive equations of the definitions of lazy listsand the operations over them (see section 4.4). For instance, the extended operators that will beintroduced in section 6 involve heavily in reasoning about the properties of all elements in a lazylist, i.e. the LL_ALL predicate. In this case the take lemma and bisimulation rule do work anymore. Fortunately, LL_ALL is defined on the “never”, which is in turn defined on the“firstPelemAt”. The expression “firstPelemAt P n ll” is true if xs has at least n+1 elements and nis the position of the first element of ll satisfying P. By inducting on this position, we can prove a

12

special proof principle for LL_ALL

P [||] ∧ ( ∀ h t. P (h:::t) ⇒ Q h ∧ P t) ∀ll. P ll ⇒ LL_ALL Q ll

which could be used to prove two important lemmas about the “transpose” operator

|- ∀P1 P2 f. (∀x. P1 (f x) ⇒ P2 x) ⇒ ∀ll. LL_ALL P1 (LMAP f ll) ⇒ LL_ALL P2 ll

|- ∀P1 P2 f. (∀x. P1 x ⇒ P2 (f x)) ⇒ ∀ll. LL_ALL P1 ll ⇒ LL_ALL P2 (LMAP f ll)

4.7 Sequence Comprehension

Inspired by mathematical set comprehensions, sequences could be constructed and iteratedover using sequence comprehensions. Thus, control at all levels, from bits to streams of blocks,could be expressed using sequence comprehensions. Combining sequence comprehensions withrecursive definitions allows us to directly express sophisticated recurrence relations that appearoften in cryptographic algorithms.

Sequence comprehensions allow element-wise specification of sequences. In Cryptol, asequence comprehension has two parts: a defining expression, and a list of generating sequences.The generating sequences provide elements and the defining expression says how to combinethose elements into an element of the resulting sequence. Here’s an example:

[|x * y || x <- xs || y <- ys |]

The sequence that results from this comprehension is defined as follows: the i-th element ofthe result sequence is defined as the value of the expression x * y, where x is equal to the i-thelement of xs, and y is equal to the i-th element of ys. The length of the new sequence is theminimum of the lengths of the generating sequences. Recurrence relations are specified inCryptol as recursive sequences. For example, the following function sums up the elements of itsargument sequence by specifying all the intermediate sums leading up to the final sum, andtaking the last element of that sequence to get the result.

sum xs = last ys where ys = [0] # [| x + y || x <- xs || y <- ys |];

HOL-4 uses similar notation to represent sequence comprehensions. The sequencecomprehension notation is analogous to set comprehension notation. A sequence is described bydrawing and combining elements from other sequences, referred to as generators. The generatorsare separated by a “|”, and the elements produced will only be as long as the elements of theshortest generator.

For instance, [| [|x;y|] || x <- [1;2] | y <- [4; … ; 7] |] is evaluated to [| [|1;4|]; [|2;5|]|].

In HOL-4, given the following sets

llist: the set of all lazy lists (and α llist denotes the set of all lazy lists of type α)

ID: the set of legal identifiers

Funs: the set of functions

SeqFuns: the set of functions over sequences (and α SeqFuns denotes the set of functions oversequences of type α)

then the syntax of the generic sequence comprehension is defined by (the brackets < > beloware used only for grouping symbols together to clarify the associability of these symbols):

SeqComp ::= <SeqGen> | <initSeq +++ SeqGen>

13

initSeq ::= α llist

SeqGen ::= <[|recSeq || generators |]> | <[|Funs || generators |]>

recSeq ::= ID is Funs

generators ::= <generator separator generators> | <generator>

generator ::= ID <- srcSeq

separator ::= | (* i.e. the character ‘|’ *)

srcSeq ::= seqFuns <llist | <α llist # ID>]>>

The syntax analyzer also checks the forms and the types in the definition, esp. those relevantto the Funs and SeqFuns, to make sure that the no inconsistence exists in the definition. Thefollowing definition is valid

[|2 * x || x <- [|2;4;6;…|]|]

[|0;1;2|] +++ [|s is x+y || x <- [|1;2;3|] | y -< (THE o LTL) ([|4|] # s)|]

and the following definitions are invalid

[|s is x+y || x <- [|1;2;3|]|] (* due to missing the generator for y *)

[|s is x+y || x <- [|1;2;3|] | [|[1]|] # s|] (* due to the type inconsistency between [1]:num list ands:num *)

The defining expression, Funs, is the next function that generates a new element of theresulting sequences from an old element. In some cases we would like to give some initial valuesof the resulting sequences through specifying the initSeq explicitly. In particular, for a recursivesequence, some initial values have to be given by the users to establish basic steps of therecursion. The generators are divided into two parts: a recursive part and a non-recursive part.Those generating sequences specified by srcSeq ::= seqFuns llist are non-recursive sequences, andthose specified by srcSeq ::= α llist # recSeq are recursive sequences. At each round, the headelements of both the recursive sequences and the non-recursive sequences are retrieved andprocessed by the next function. After the next function generates a new element, this newelement is appended to the recursive sequences. If there are more than one generating sequencesin the recursive parts, then the new element is appended to each of them. However, since inordinary cases sequence comprehension always produces one result sequence, all the new data ofthe recursive sequences are from this result sequence (we will discuss the mutual recursion casein the next section).

After the syntax analyzer supplies the set of non-recursive sequences non_rec, recursivesequences rec and the next function genF, the sequence comprehension interpreter generates anequivalent (possibly infinite) sequence corecursively by defining a next function for processingthe sequence comprehension and applying this function to the LUNFOLD operator. At each round,this function checks whether there is any non-recursive sequence reaching its end, if so thenterminates. Otherwise, it applies the genF to the heads of all generating sequences (if thereexists no recursive sequences then the genF works only on the heads of non-recursive sequences).Then, the new element generated by the genF is appended to the non-recursive sequences.

(* Psuedo-codes of the function processing sequence comprehensions *) (* Input: (genF, rec, non_rec) *)

if there exists s ∈ non_rec such that LTL s = NONE then return NONEelse let non_rec_t be the set of tails of the sequences in non_rec in

let non_rec_h be the set of heads of the sequences obtained by applying the seqFun to the non_rec in let newEL = case LHD (seqFun rec) of

14

NONE -> genF ARB non_rec_h || SOME rec_h -> genF rec_h non_rec_h

in let newRec = case LTL rec of NONE -> [|newEL|] || SOME rec_t -> rec_t +++ [|newEL|] in SOME ((genF, newRec, rec_t), newEL)))

For example, the following sequence comprehension with two non recursive sequences, anempty recursive sequence and the next function (λx y. [x;y])

[| [x;y] | x <- [|1;3;5;7;9|] | y <- [|2;4;6;8|] |]

is evaluated to be [|[0;4]; [0;5]; [0;6]; [0;7]; [1;4]; [1;5]; [1;6]; [1;7]|]As an illustrative example, we define the fibinacci sequence using sequence comprehension

fibs_Seq = [|0 ;1|] +++ [| z is x + y || x <- [||] # z | y <- (THE o LTL] ([||] # z)|]

An alternative definition is

fibs_Seq = LMAP (\(x,y).x) ([| z is (SND x, FST x + SND x) || x <- [|(0,1)|] # z|]

We first check the first few elements of this sequence

|- LTAKE 9 fibs_Seq = SOME [0; 1; 1; 2; 3; 5; 8; 13; 21]

Then we verify the correctness of this definition

|- ∀n. LNTH (n + 2) fibs_Seq = SOME (THE (LNTH (n + 1) fibs_Seq) + THE (LNTH n fibs_Seq))

4.7 Sequence Comprehension with Mutual Recursion

In Cryptol, there are cases of mutual recursion where two or more sequences are bothrecursive and updated in terms of each other. In HOL-4, mutual recursion doesn’t bring anytrouble to the coinductively defining approach. For instance, the key schedule in RC6 [12]involves mutual recursion between two sequences, S and L, in such a way that at each round theheads of sequence S and L are retrieved to generate a and b, and then a and b are appended to Sand L respectively. As long as we separate the processing of these recursive sequences, thisproblem is solved swiftly

RC6KeySchedFun s = (let (S,L,a,b) = s in let a = (THE (LHD S) + a + b) #<< 3 in let b = (THE (LHD L) + a + b) <<< (a + b) in SOME ((LAPPEND (THE (LTL S)) [|a|], LAPPEND (THE (LTL L)) [|b|],a,b),a))

We augment the definition of sequence comprehensions to account for mutual recursion caseas follows.

SeqGen ::= <[|recSeqs || generators |]> | <[|Funs || generators |]>

recSeqs ::= <recSeqs ∧ recSeq> | recSeq

recSeq ::= ID is Funs

generators ::= <generator separator generators> | <generator>

generator ::= ID <- srcSeq

separator ::= |

srcSeq ::= seqFuns <llist | <llist # ID>>

At each round, all components in the recSeqs would be “zipped” into a tuple and returned as

15

the new element generated at that round. And, before they are appended to individual recursivegenerators, this tuple is “unzipped” to restore individual components some of which would beappended to appropriate generators.

Using this augmented notion, the key schedule of RC6 is defined as

LMAP (λ(x,y). x) [|a is h1 + a’ + b’ ∧ b is f2|| h1 <- S # a | h2 <- L # b | a’ <- [|0|] # a | b’ <- [|0|] # b|]

where

f2 = let a = (h1 + a’ + b’) #<< 3 in h2 + a + b’ <<< (a + b)

and S and L are the initial sequences.

5. Extended Sequence Operations

There is a rich set of operators for manipulating sequences, including basic ones likesequence concatenation (#), and sequence indexing (@).This section describes the way to modelCryptol ‘s sequence operators in HOL-4.

5.1 Basic Sequence Operator

In HOL-4, llistTheory provides some basic operators for lazy lists. These operators performvirtually the same operations as their counterparts in Cryptol except that their return types areoptions: when the operation is invalid, option NONE would be returned to indicate the failure ofthe operation; otherwise valid data is returned. For example, when we attempt to use a out-of-range index to index an element in the sequence, a NONE would be returned to indicate that thisoperation is invalid.

The following table lists the basic sequence operators in Cryptol and their counterparts inHOL-4 that is already defined by the llistTheory.

Operators inCryptol

CorrespondingOperators in HOL-

4

Description

Width LLENGTH Return the number of elements in the top level of theargument sequence.

@ (Select) LNTH Index an element in the sequence.# (Concatenate) LAPPEND Concatenate two sequences.Join LFLATTEN Concatenate the elements of a sequence.Take LTAKE Construct a new sequence by taking the first n elements of

the argument sequence.Drop LDROP Construct a new sequence by leaving out the first n

elements of the argument sequence.Tail LTL Drop the first element of a sequence

Operators LZIP and LUNZIP are among the most frequently-used operations of lazy lists. Wedefine them as follows

LZIP ([||],[||]) = [||])LZIP (x1:::ll1,x2:::ll2) = (x1,x2):::LZIP (ll1,ll2)

LUNZIP [||] = ([||],[||])LUNZIP ((x,y):::t) = (let (ll1,ll2) = LUNZIP t in (x:::ll1,y:::ll2))

LZIP combines the two lazy lists ll1 and ll2 into a lazy list of pairs, with the first element ofeach lazy list comprising the first element of the result and the second elements comprising thesecond element of the result. It works only for two lazy lists of the same length. LUNZIP returns a

16

pair of lazy lists formed by splitting the elements of input lazy list. It is the inverse of zip forequal length lists. The following two theorems verify the reversibility of these two operations.

|- ∀ll. LZIP(LUNZIP ll) = ll

|- ∀ll1 ll2. (LLENGTH ll1 = LLENGTH ll2) ⇒ (LUNZIP(LZIP(ll1, ll2)) = (ll1, ll2))

5.2 Permute and Reverse

Bulk indexing, useful as a permutation operator, is defined in Cryptol as:

xs @@ is = [| xs @ i || i <- is |]

For example, [1 2 3] @@ [2 0 2] is evaluated to be [3 1 3].

In HOL-4, bulkIndex is given by:

l1 @@ [||] = [||])l1 @@ (h2:::t2) = l1 & h2:::l1 @@ t2

Operator “reverse” reverses the (top-level) elements of the sequence. For example, reverse[1 2 3 4] = [4 3 2 1]. In HOL-4, reverse is implemented based on the “REVERSE” operator in list.

LREVERSE ll =SOME (fromList (REVERSE (THE (toList ll))) if LFINITE llNONE otherwise

The following is the basic property of the reverse operation.

|- (LREVERSE [||] = SOME [||]) ∧ (LREVERSE (h:::t) = OPTION_MAP (λx. x +++ [|h|]) (LREVERSE t))

Reverse the reverse of a given sequence will restore this sequence.

|- ∀l. (LFINITE l ⇒ (OPTION_JOIN (OPTION_MAP LREVERSE (LREVERSE l)) = SOME l)) ∧ (~LFINITE l ⇒ (OPTION_JOIN (OPTION_MAP LREVERSE (LREVERSE l)) = NONE))

5.3 Split, SplitBy and GroupBy

A common step in crypto-algorithms is to divide words into smaller pieces, such as dividing a128-bit word into 4 32-bit words or joining small pieces together. Cryptol provides two built-infunctions, split and splitBy to make this particularly convenient.

The split operator is quite flexible. Its interpretation depends on the type of the inputsequence. Fortunately, the split operator could be modeled easily by the splitBy operator thatspecifies explicitly how many pieces the input sequence should be split into. In HOL-4, we usesplitBy to simulate the split operator.

splitBy. Operator splitBy splits a sequence n ways. Each time it takes a fixed number of elementsout from the source sequence to constitute a new subsequence of the result. Note that thisoperation is invalid for infinite sequence, since the size of the input sequence must be an evenmultiple of the split factor for the operation to be valid.

LSPLITBY 0 ll = SOME [||] LSPLITBY (SUC n) ll = case LLENGTH ll of NONE -> NONE || SOME v -> case OPTION_MAP fromList (LTAKE (v DIV SUC n) ll) of

17

NONE -> NONE || SOME v' -> case LSPLITBY n (THE (LDROP (v DIV SUC n) ll)) of NONE -> NONE || SOME v -> SOME (v':::v)

Split an empty sequence 0 ways gives an empty sequence of the same type.

|- LSPLITBY 0 [||] = SOME [||]

In the regular case where the size of the input sequence must be a multiple of the splitfactor, this operator exhibits good recursion behaviors.

|- ∀x n ll.(LLENGTH ll = SOME ((SUC n)*x)) ⇒ (LSPLITBY (SUC n) ll = SOME (fromList(THE(LTAKE x ll)):::(THE(LSPLITBY n (THE (LDROP x ll))))))

In the irregular case where the size of the input sequence is not a multiple of the split factor,the operation is invalid.

|- ∀x n ll.~(LLENGTH ll = SOME (n*x)) ⇒ (LSPLITBY n ll = NONE)

SplitBy does divide the input sequence into n pieces.

|- ∀x n ll. (LLENGTH ll = SOME (n*x)) ⇒ (LLENGTH (THE (LSPLITBY n ll)) = SOME n)

Each piece is of the same length.

|- ∀x n ll. (LLENGTH ll = SOME (n*x)) ⇒ LL_ALL (λmem. LLENGTH mem = SOME x) (THE (LSPLITBY n ll))

Joining the pieces together will restore the original sequence.

|- ∀x n ll. (LLENGTH ll = SOME (n*x)) ⇒ (join(THE (LSPLITBY n ll)) = ll)

GroupBy. GroupBy splits a sequence into n-wide pieces. The function groupBy provides acomplementary functionality to splitBy. Rather than giving n pieces, we get pieces each of whichis n wide. This operator is somewhat similar to the splitBy operator. But there is a big difference:groupBy works for infinite sequence while splitBy doesn’t. Hence, we define the groupBy operatorcorecursively.

LGROUPBY n ll = case OPTION_MAP fromList (LTAKE n ll) of NONE -> [||] || SOME v -> v:::LGROUPBY n (THE (LDROP n ll))

When the size of the input sequence ll is a multiple of the group factor, or the inputsequence ll is infinite (i.e. LLENGTH ll = NONE), the operation is valid and pieces of length n aregiven. When the size of ll is not a multiple of the group factor, then pieces of length n are stillreturned, with the last few elements that cannot constitute an n-element group are discarded.

LGROUPBY satisfies some recursive equations

∀x n ll.(LLENGTH ll = SOME (SUC n * SUC x)) ⇒ (LGROUPBY (SUC x) ll = (fromList(THE(LTAKE (SUC x) ll)):::(LGROUPBY (SUC x) (THE (LDROP (SUC x)ll)))))

For regular and finite input sequence, groupBy and splitBy are convertible to each other.

|- ∀x n ll. (LLENGTH ll = SOME (SUC x * SUC n)) ⇒

18

(SOME (LGROUPBY (SUC n) ll) = LSPLITBY (SUC x) ll)

groupBy does divide the input sequence into n pieces.

|- ∀x n ll. (LLENGTH ll = SOME (x*n)) ⇒ (LLENGTH (LGROUPBY x ll) = SOME n)

Each piece is of the same length.

|- ∀x n ll. (LLENGTH ll = SOME (SUC x * n)) ∨ (LLENGTH ll = NONE) ⇒ LL_ALL (λmem. LLENGTH mem = SOME x) (LGROUPBY x ll)

Joining the pieces together will restore the original sequence.

|- ∀x n ll. (LLENGTH ll = SOME (SUC x * n)) ∨ (LLENGTH ll = NONE) ⇒ (join(LGROUPBY (SUC x) ll) = ll)

5.4 Transpose

The “transpose” operator transposes the top two levels of the nested sequence. For example,transpose [[1 2 3] [4 5 6] [7 8 9]] = [[1 4 7] [2 5 8] [3 6 9]].

In HOL-4, “transpose” is defined as

LTRANSPOSE_f ll = SOME (LMAP (THE o LTL) ll,LMAP (THE o LHD) ll) if ~(ll = [||]) ∧ LL_ALL (λx. ~(x = NONE)) (LMAP LTL ll) NONE otherwise

For the LTRANSPOSE operation to be valid, the input lazy list should conform to matrix forms–- all the subsequence at the top level should be of the same length (corresponding to the factthat all rows in the matrix should have the same length). llistTheory provides a predicate LL_ALLto specify that all elements in a lazy list should satisfy the same given predicate. For instance,LL_ALL (λel. LLENGTH el = SOME 0) ll specifies that ll is a sequence of empty sequences, i.e. ll =[|[||],[||],[||], …|].

Transposing an empty sequence would give itself --- the empty sequence of the same type.

[LTRANSPOSE_NIL]|- LTRANSPOSE [||] = [||]

Transposing a sequence of empty sequences also give an empty sequence. To justify this,consider an m×0 matrix, its transpose is a 0×m matrix. In lazy list format, this property illustratesLTRANSPOSE [|[||],[||],[||], …|] = [||].

[LTRANSPOSE_ALL_NIL]|- ∀ll. LL_ALL (λel. LLENGTH el = SOME 0) ll ⇒ (LTRANSPOSE ll = [||])

For any matrix M, (transpose M)i,j = Mj,i.

[EL_OF_TRANSPOSE_THM]|- ∀ll len i j. LL_ALL (λel. LLENGTH el = len) ll ⇒ (EL i j (LTRANSPOSE ll) = EL j i ll)

Here EL i j denotes the element at the ith row and the jth column of the matrix, i.e.

EL i j ll = OPTION_JOIN (OPTION_MAP (LNTH j) (LNTH i ll))

For an m×n matrix M, its transpose is an n×m matrix. That is, the number of elements in eachrow of the transpose of M equals to the number of rows in M, and the number of rows in thetranspose of M equals to the number of elements in each row of M.

[LLENGTH_EL_OF_TRANSPOSE]|- ∀ll len.

19

LL_ALL (λel. LLENGTH el = len) ll ⇒ LL_ALL (λel. LLENGTH el = LLENGTH ll) (LTRANSPOSE ll)

[LLENGTH_OF_TRANSPOSE_THM]|- ∀ll len. ~(ll = [||]) ∧ LL_ALL (λel. LLENGTH el = len) ll ⇒ (LLENGTH (LTRANSPOSE ll) = len)

The transpose of the transpose of M should be M itself. There is one exception: when M is asequence of empty sequences, i.e. an m×0 matrix, transpose M is [||], thus transpose (transposeM) is [||] rather than [|[||],[||],[||], …|].

[TRANSPOSE_TRANSPOSE]|- ∀ll len.

~(len = SOME 0) ⇒ LL_ALL (λel. LLENGTH el = len) ll ⇒ (LTRANSPOSE (LTRANSPOSE ll) = ll)

The proof of the last theorem is not trivial and is a good example to illustrate how to reasonabout possibly infinite sequences. The basic proving process of this theorem runs as follows:

1. First we use the bisimulation rule to prove that

∀ll1 ll2. ((∀i j. EL i j ll1 = EL i j ll2) ∧ (LLENGTH ll1 = LLENGTH ll2)) = (ll1 = ll2)

2. Then theorems EL_OF_TRANSPOSE_THM, LLENGTH_EL_OF_TRANSPOSE, LLENGTH_OF_TRANSPOSE_THMare proven.

3. Next, according to above theorems, the number of elements in each row of the transpose of an m×nmatrix M is equal to m, so the number of elements in the transpose of the transpose of M equals to mas well. Thus, we conclude that LLENGTH M = LLENGTH (LTRANSPOSE (LTRANSPOSE M)). Now theresults given at step one along with the EL_OF_TRANSPOSE_THM gives the TRANSPOSE_TRANSPOSEtheorem immediately.

6. An Example: RC6

RC6 is a block cipher based on RC5 and designed by Rivest, Sidney, and Yin for RSA Security[12]. Like RC5, RC6 is a parameterized algorithm where the block size, the key size, and thenumber of rounds are variable; again, the upper limit on the key size is 2040 bits. There are twomain new features in RC6 compared to RC5: the inclusion of integer multiplication and the use offour b/4-bit working registers instead of two b/2-bit registers as in RC5 (b is the block size).Integer multiplication is used to increase the diffusion achieved per round.

We implemented two streamed versions of RC6 in our sequence model. The first one workson both lazy lists and words, and doesn’t use sequence comprehensions. It illustrates how todefine loops corecursively using the LUNFOLD operator. In the second one the basic computationblock is bit sequences rather than words, thus all the data structures in this implementation aresequences. In this implementation the sequence comprehension notion is used to define roundfunction.

In these two implementation, r is the number of rounds in encryption (and in decryption aswell). Since we have shown the definitions of key schedules in section 4.7, in this section we onlygive the definitions of round functions in encryption and decryption.

6.1 Implementation 1

First we give the basic operations in the round operations in encryption and decryption.

CompUT x = (x * (x + x + word_1)) #<< 5;

20

(* Operations performed in the encrypting rounds *)

FwdRound ((a,b,c,d):block) ((k0,k1):key) = (b, ((c # CompUT d) <<< CompUT b) + k1, (*c = (c xor u <<< t) + k1*) d, ((a # CompUT b) <<< CompUT d) + k0);

(* Operations performed in the decrypting rounds *)

BwdRound ((a,b,c,d):block) ((k0,k1):key) = (* Note that let val (a,b,c,d) = (d,a,b,c) *) (((d - k0) >>> CompUT c) # CompUT a, (*a = ((a - k0) >>> u) xor t*) a, ((b - k1) >>> CompUT a) # CompUT c, (*c = ((c - k1) >>> t) xor u*) c);

Then the next functions corresponding to the FwdRound and BwdRound are defined. Byapplying the LUNFOLD operator to the RoundFun, we get an infinite stream consisting of roundstates, and the r-1th state contains the encrypted text we need. Analogously, we get an infinitefor decryption where the plaintext can be restored from the r-1th item.

RoundFun s = (let newS = (ROTKEYS (FST s),FwdRound (SND s) (GETKEYS (FST s))) in SOME (newS,newS))

InvRoundFun s = (let newS = (INVROTK (FST s), BwdRound (SND s) (GETKEYS (INVROTK (FST s)))) in SOME (newS,newS))

6.2 Implementation 2

In this implementation words are replaced with bit sequences in the definitions. However,since we don’t define arithmetic operations such as shifting and xor on bit sequences, we wouldconvert the sequences back to words when such operations are needed. Using bit sequencesinstead of words here is just to show that cryptographic algorithms can be implemented oversequences unanimously in HOL-4. Here m denotes the size of the words (or the length of the fixedlength bit sequences). In addition, sequence comprehensions are used to define round functionsof encryption and decryption.

FwdRound ((a,b,c,d):block) ((k0,k1):key) =let (a,b,c,d,k0,k1) = (toWord m a, toWord m b, toWord m c, toWord m d, toWord m k0, toWord m k1) in

(fromWord m b, fromWord m (((c # CompUT d) <<< CompUT b) + k1), fromWord m d, fromWord m (((a # CompUT b) <<< CompUT d) + k0));

BwdRound ((a,b,c,d):block) ((k0,k1):key) =let (a,b,c,d,k0,k1) = (toWord 32 a, toWord 32 b, toWord 32 c, toWord 32 d, toWord 32 k0, toWord 32 k1) in

(fromWord m (((d - k0) >>> CompUT c) # CompUT a), fromWord m a, fromWord m (((b - k1) >>> CompUT a) # CompUT c), fromWord m c);

For the encryption, given the state after the initial round (pre-whitening round) EncryptS1and the key schedule sequence keysched, the sequence of states in encrypting rounds is given by

encryptSeq = [|new_s is FwdRound(old_s, k) || old_s <- [|EncryptS1|] # new_s | k <- keysched|]

For the decryption, given the state after the initial round DecryptS1 and the key schedulesequence keysched, the sequence of states in decrypting rounds is given by

21

decryptSeq = [|new_s is FwdRound(old_s, k) || old_s <- [|EncryptS1|] # new_s| k <- (THE o LREVERSE) keysched |]

The ciphered text and the restored plaintext are given by

THE (LNTH (r-1) (LMAP (λ(x,y). x) encryptSeq)) and THE (LNTH (r-1) (LMAP (λ(x,y). x) decryptSeq)) respectively.

6.3 Reversibility of the Encryption and the Decryption

We have given mechanized formal proofs of symmetric key block encryption algorithms (AES,MARS [13], Twofish, RC6, Serpent, IDEA, and TEA) [14]. For each algorithm, functionalcorrectness, namely that decryption inverts encryption, is formally proved by a simple, buteffective proof methodology involving application of invertibility lemmas in the course ofsymbolic evaluation. The implementations of these algorithms in HOL-4 are not based on streams.

We also implement MARS, Twofish, RC6 and TEA in our stream model and verify theirfunctional correctness by similar proof methodology. The approach (discussed more fully in thesequel) amounts to symbolic evaluation of the formula

∀key plaintext. decrypt key (encrypt key plaintext) = plaintext

In this section we show the reversibility of the encryption and decryption of RC6. We firstshow that round operations performed during encryption are inverted by their counterparts indecryption.

∀b k. BwdRound (FwdRound b k) k = b

Given a couple of properties about operations over words such as shifting and xor, the proveof above theorem goes swiftly

∀a b. a + b – b = a ∀a. a + 0 = a∀a i. (a <<< i >>> i = a) ∧ (a >>> I <<< i = a)

For reasoning about the states in the encrypting stream StreamG, we define a function tounroll the states

Rounds 0 (s:state) = s Rounds (SUC n) s = (Rounds n (ROTKEYS (FST s), FwdRound (SND s) (GETKEYS (FST s))));

Then a lemma for indexing the states in the encrypting stream is derived

∀s. THE (LNTH n (StreamG(s))) = Rounds (SUC n) s

Similar unrolling function is defined for decrypting stream InvStreamG, and the indexinglemma for this stream is proven as well. The following theorem is carried out by unfolding eachof the two unrolling functions r times.

∀s. InvRounds r (Rounds r s) = s

Then the reversibility of r encrypting rounds and r decrypting rounds is obtained

∀plaintext keys. RC6Decrypt keys (RC6Encrypt keys plaintext) = plaintext

which implies

|- ∀key plaintext.

((encrypt,decrypt) = RC6 key) ⇒ (decrypt (encrypt plaintext) = plaintext)

22

7. Conclusion

In this paper we investigate links between HOL-4 and Cryptol, and develop mathematicaltheories to model the semantics of Cryptol. Sequences, the basic building blocks in Cryptol forcryptographic algorithms such as block ciphers and stream ciphers, are modeled as lazylists/words in HOL-4. We implemented all the sequence operations defined in Cryptol and proveda variety of properties of these operations, plus providing proof principles to facilitate thereasoning about possible infinite sequences. We built a model to process sequencecomprehensions over which sequences could be constructed and iterated. Furthermore, thesetechniques are applied concrete cryptographic algorithms including TEA, RC6, MARS and Twofish.Streamed versions of these algorithms are implemented on our stream model, and theirfunctional correctness is verified by simple and effective proof methodology involving applicationof invertibility lemmas in the course of symbolic evaluation.

Reference

[1] Jeffrey R. Lewis and William B. Martin. Cryptol: High Assurance, Retargetable CryptoDevelopment and Validation. MILCOM 2003.

[2] Cryptol Reference Manual. Available at: http://www.cryptol.net/doc.htm.[3] Michael Norrish and Konrad Slind, HOL-4 manuals, 1998-2005, Available at

http://hol.sourceforge.net/.[4] Paul Lawrence. Isabelle: A Generic Theorem Prover. LNCS 828. Springer-Verlag, 1994.[5] Franz Regensburger. HOLCF: Higher Order Logic for Computable Functions. Higher Order Logic

Theorem Proving and its Applications, LNCS 971. Springer-Verlag, 1995.[6] S.Owre, J.Rushby, N.Shankar and F. von Henke. Formal verification for fault-tolerant architectures:

Prolegomena to the design of PVS. IEEE Trans. On Software Engineering, 21(2):107-125,February 1995.

[7] Ching-Tsun Chou and Doron Peled. Formal verification of a partial-order reduction technique formodel checking. Proc. 2nd Workshop Tools and Algorithms for the Construction and Analysis ofSystems (TACAS’96), LNCS 1055. Springer-Verlag, 1996.

[8] Lawrence C. Paulson. Logic and Computation. Cambridge University Press, 1987.[9] John Matthews. Recursive Function Definition over Coinductive Types. Proceedings of the 12th

International Conference on Theorem Proving in Higher Order Logics, 1999.[10] United States National Institute of Standards and Technology, Advanced Encryption Standard,

Web: http://csrc.nist.gov/encryption/aes/, 2001.[11] B. Schneier, J. Kelsey, D. Whiting, D. Wagner, C. Hall, and N. Ferguson, The Twofish encryption

algorithm, John Wiley and Sons, 2003.[12] R. Rivest, M. Robshae, R. Sidney, and Y.L. Yin, The RC6 block cipher, Available at

http://www.rsasecurity.com/rsalabs/rc6, August 1998.[13] C. Burwick, D. Coppersmith, E. D’Avignon, R. Gennaro, S. Halevi, C. Jutla, S. Mathas Jr., L.

O’Connor, M. Peyravian, D. Safford, and N. Zunic, MARS - a candidate cipher for AES, Availableat http://www.research.ibm.com/security/mars.pdf, September 1999.

[14] Joan Daemen and Vincent Rijmen, The design of Rijndael: AES - the Advanced EncryptionStandard, Information Security and Cryptography, no. 17, Springer- Verlag, 2002.

[15] R. Anderson, E. Biham, and L. Knudsen, Serpent: A proposal for the advanced encryption standard,Available at http://www.cl.cam.ac.uk/˜rja4/serpent.html, August 1998.

[16] Jianjun Duan, Joe Hurd, Guodong Li, Scott Owens, Konrad Slind, and Junxing Zhang. FunctionalCorrectness Proofs of Encryption Algorithms, submitted.

[17] A. Church, "A Formulation of the Simple Theory of Types", Journal of Symbolic Logic Vol. 5 (1940),pp. 56-68.

23

Appendix (Cryptol Codes of RC6)// Parameters:r = 20; // Number of roundsW = 32; // Word size measured in bitsWW = W / 8; // Word size measured in bytesB = 4 * W; // Block size

T : [32];T = 2 * (r+2); // Length of expanded key

// These two must be PW, and QW, depending on wheter W =16, 32, and 64.Pw = P32;Qw = Q32;

//Key schedule for RC6rc6ks : {a} (32 >= width (4*a), 63 >= a) => [4*a][8] -> [T][W];rc6ks K = S @@ [(v-T) .. (v-1)] where { LL = width K / WW; v = 3 * max (LL, T); Si : [T][W]; Si = take (T, [Pw (Pw+Qw) ..]); Li : [LL][W]; Li = splitBy (LL, join K); S = [| (s+a+b) <<< 3 || s <- Si # S || a <- [0] # S || b <- [0] # L |]; L = [| (l+a+b) <<< (a+b) || l <- Li # L || a <- S || b <- [0] # L |]; };

//Rounds of RC6 Encryptionrc6e : {a b} (b >= 2,a >= 0) => ([2*(a+2)][b], [4][b]) -> [4][b];rc6e (S, PT) = CT' where { // B = B + S[0], D = D + S[1] PT' = [(PT@0) (PT@1 + S@0) (PT@2) (PT@3 + S@1)]; CT = rounds @ (r-1); CT' = [(CT@0 + S@(2*r+2)) (CT@1) (CT@2 + S@(2*r+3)) (CT@3)]; rounds = [| [b' c' d' a'] where { t = (b * (2*b + 1)) <<< 5; u = (d * (2*d + 1)) <<< 5; a' = ((a ^ t ) <<< u ) + S@(2*n); c' = ((c ^ u) <<< t) + S@(2*n+1); b' = b; d' = d; } || [a b c d] <- [PT'] # rounds || n <- [1..r] |]; };

//Rounds of RC6 Decryptionrc6d : {a b} (b >= 2,a >= 0) => ([2*(a+2)][b], [4][b]) -> [4][b];rc6d (S, CT) = PT' where {

24

//C = C - S[2r+3], A = A - S[2r+2] CT' = [(CT@0 - S@(2*r+2)) (CT@1) (CT@2 - S@(2*r+3)) (CT@3)]; PT = rounds @ (r-1); //D = D - S[1], B = B - S[0] PT' = [(PT@0) (PT@1 - S@0) (PT@2) (PT@3 - S@1)]; rounds = [| [a' b' c' d'] where { //(A,B,C,D) = (D,A,B,C) a1 = d; b' = a; c1 = b; d' = c; u = (d' * (2*d' + 1)) <<< 5; t = (b' * (2*b' + 1)) <<< 5; c' = ((c1 - S@(2*(r-n+1)+1)) >>> t) ^ u; a' = ((a1 - S@(2*(r-n+1)))>>> u ) ^ t; } || [a b c d] <- [CT'] # rounds || n <- [1..r] |]; };

rc6_encrypt(K, PT) = CT where { xK = rc6ks K; CT = join (rc6e (xK, splitBy(4, PT))); };

rc6_decrypt(K, CT) = PT where { xK = rc6ks K; PT = join (rc6d (xK, splitBy(4, CT))); };

// Pre-computed constants:P16, Q16 : [16];P16 = 0xb7e1;Q16 = 0x9e37;

P32, Q32 : [32];P32 = 0xb7e15163;Q32 = 0x9e3779b9;

P64, Q64 : [64];P64 = 0xb7e151628aed2a6b;Q64 = 0x9e3779b97f4a7c15;

25


Recommended