Download Expi2Java Tutorial
Transcript
Expi2Java Tutorial Generating Code For The Perrig-Song Protocol Alex Busenius July 29, 2009 1 Introduction This tutorial presents the process of writing a formal specification and generating runnable code for the Perrig-Song mutual authentication protocol1 . We will start with an informal specification of the protocol and write a formal specification in the Extensible Spi Calculus. We will use an iterative approach, we will write the protocol specification step-by-step and add the needed configurations as we need them. Finally, we will generate Java code implementing the protocol and test the interaction between the participants. 2 Informal Specification The Perrig-Song protocol is given in Figure 1. Alice Bob / (Alice, NA ) o enc((NA , NB , Bob), KAB ) enc((NB , M ), KAB ) / Figure 1: Perrig-Song mutual authentication protocol The Perrig-Song protocol uses a shared key to authenticate two participants and send an encrypted message. It is composed of three message exchanges. First, the initiator of the protocol, Alice, sends her identity together with a fresh nonce NA to the responder, Bob. Bob encrypts the nonce NA , which he received from Alice together with another fresh nonce NB and his identity with the shared key KAB and sends this encryption to Alice. Alice receives the encrypted message, decrypts it with the shared key KAB and checks that the nonce NA0 inside is the same as her nonce NA . If the nonces match, she encrypts the received nonce NB and a message M 1 Can be found as one of the examples for CAPSL by J. Millen et al. [MM01], at http://www.csl.sri.com/ users/millen/capsl/examples.html 1 she wanted to send with the shared key KAB and sends the resulting message to Bob. Bob decrypts the message and checks that the received nonce NB0 is the same as his nonce NB . If the nonces match, the protocol completes successfully. We will assume that the identities are UTF-8 encoded strings, nonces are randomly chosen 64 bit integers, and the used encryption is AES 256. Further, we will use the usual Java key store mechanism to store the shared key in the file key.store that is supposed to be first shared between Alice and Bob in a secure way. For communication we will use TCP/IP, the data will be sent from IP 127.0.0.1 to IP 127.0.0.1 on the port 1234. The localhost is only used here for convenience, the example can be easily extended to use the LAN by specifying the according IP addresses in the configuration. The message that Alice sends to Bob will be an UTF-8 encoded string. We will generate two programs called progA and progB, one for each participant. Since TCP/IP assumes one of the participants to be a server and all other to be clients, progB will act as a server and progA will act as a client. For simplicity, both programs will have a simple command line interface. In a successful protocol run, progA will prompt the user to enter the message and progB will display the received message. In case of an error the programs will abort with an error message. 3 Formal Specification in Extensible Spi Calculus We will write the formal specification iteratively, message by message. First, we create two new files in testData/expi/, perrigsong.expi and perrigsong.exdef. To be able to use the provided types and constructors (see the “Input Language” Section of User Manual) we include the file default.exdef. We will put all custom configurations into perrigsong.exdef, it should also be included. Furthermore, we add two empty processes named pA and pB, and let them be executed in parallel to model the interaction of two participants: 1 2 3 4 5 6 7 (∗ ∗ P e r r i g −Song m u t u a l a u t h e n t i c a t i o n p r o t o c o l ∗ ∗ h t t p : / /www . c s l . s r i . com/ u s e r s / m i l l e n / c a p s l / e x a m p l e s . h tm l ∗ h t t p : / / s p a r r o w . e c e . cmu . edu /˜ a d r i a n / p r o j e c t s / p r o t g e n −c s f w / c s f w . p d f ∗ eXpi v e r s i o n ∗) 8 9 10 include ” . . / exdef / default . exdef ” include ” perrigsong . exdef ” 11 12 13 14 l e t pA = 0. 15 16 17 l e t pB = 0. 18 19 20 process ( pA | pB ) Listing 1: Simple setup: perrigsong.expi 2 The configuration file only contains a comment for now: 1 2 3 (∗ ∗ P e r r i g −Song p r o t o c o l c o n f i g u r a t i o n ∗) Listing 2: Simple setup: perrigsong.exdef 3.1 First Message In the first message Alice sends a concatenation of her identity and a fresh nonce to Bob over a communication channel. To do this, we first need to set up a channel, declare the needed variables and generate a nonce. In general, constant terms can be modelled in two different ways, as free variables or fresh names. Fresh names are generated using the restriction process new a; P and must initialized using configurations. The disadvantage of the restriction processes is however that it can only handle terms of generative types. Free variables are declared using the free a construct and can have any type, but must be initialized manually by modifying the generated code. Identities of both participants are constant strings, we can use the generative type ConstStr and configuration ConstStrCfg to model them, but there is also a specialized configuration IdentifierCfg that is used together with the non-generative type String to model identifiers. As an example, we will use both representations, a free variable alice of type $Identifier as Alice’s identity and a fresh name bob of type String as Bob’s identity. In order to declare Alice’s identity, we only need to add the declaration line with the type annotation just before process: free a l i c e : $ I d e n t i f i e r process ( pA | pB ) Listing 3: Added Alice’s identity: perrigsong.expi Generating Bob’s identity as a fresh name requires adjusting the ConstStrCfg configuration (we need to set up the value of the generated string). First, we create a configuration called BobIdCfg by extending ConstStrCfg in perrigsong.exdef: c o n f i g B o bIdCfg e x t e n d s C o n s t S t r C f g ( message = ” bob ” ). Listing 4: Added BobIdCfg: perrigsong.exdef Then we create a fresh name bob in the main process (it should be visible in both named processes): process new bob : C o n s t S t r @ B o b I d C f g ; ( pA | pB ) Listing 5: Added Bob’s identity: perrigsong.expi 3 Now we need to set up the communication channel for the first message. First, we create two TCP/IP channel configurations, one for each participant, and set them up according to the informal specification. We will also need to enter the type of the first message soon, we don’t know it at this point, but we can already create a dummy typedef for it. c o n f i g ChanA e x t e n d s T c p I p C h C f g ( ( ∗ c l i e n t ∗ ) variable = ”cA” , host = ” 1 2 7 . 0 . 0 . 1 ” , (∗ i p of the s e r v e r ∗) port = ” 1234 ” ). c o n f i g ChanB e x t e n d s T c p I p C h C f g ( ( ∗ s e r v e r ∗ ) variable = ”cB” , host = ” any ” , ( ∗ l i s t e n s on a l l h o s t s ∗ ) port = ” 1234 ” ). t y p e d e f $Msg1 = Top . Listing 6: Channel configurations: perrigsong.exdef Now we create a common channel c1 and start a server on Bob’s side by calling accept(). We use the typedef $Msg1 as the type of the first message. l e t pB = ( ∗ l i s t e n t o c o n n e c t i o n s on c1 ∗ ) l e t c1 = a c c e p t [−>@ChanB ] ( c1 ) i n 0. ... process new bob : C o n s t S t r @ B o b I d C f g ; ( ∗ c r e a t e common c o m m u n i c a t i o n c h a n n e l ∗ ) new c1 : Channel@ChanA<$Msg1 >; ( pA | pB ) Listing 7: Created a common channel: perrigsong.expi Finally, we generate a fresh nonce and let Alice send it in the first message. We define a configuration for the 64-bit nonce and a short typedef for convenience: c o n f i g PSNonceCfg e x t e n d s NonceCfg ( s i z e = ”8” ). t y p e d e f $PSNonce = Int@PSNonceCfg . Listing 8: Nonce configuration: perrigsong.exdef In Alice’s process, we generate a fresh nonce and send the first message. In Bob’s process, we receive the message and give both components a name: l e t pA = ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) new Na : $PSNonce ; out ( c1 , ( a l i c e , Na ) ) . l e t pB = ... 4 ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) i n ( c1 , ( name , Na ) ) . Listing 9: First message: perrigsong.expi At this point, we can finally correct the type of the first message we preliminary set to Top, it should be ( $Identifier , $PSNonce). Additionally, we define a shorter typedef for ConstStr@BobIdCfg and use it in the code. As the result, we get: 1 2 3 (∗ ∗ P e r r i g −Song p r o t o c o l c o n f i g u r a t i o n ∗) 4 5 6 7 c o n f i g B o bIdCfg e x t e n d s A S C I I S t r i n g C f g ( message = ” bob ” ). 8 9 10 11 12 13 c o n f i g ChanA e x t e n d s T c p I p C h C f g ( ( ∗ c l i e n t ∗ ) variable = ”cA” , host = ” 1 2 7 . 0 . 0 . 1 ” , (∗ i p of the s e r v e r ∗) port = ” 1234 ” ). 14 15 16 17 18 19 c o n f i g ChanB e x t e n d s T c p I p C h C f g ( ( ∗ s e r v e r ∗ ) variable = ”cB” , host = ” any ” , ( ∗ l i s t e n s on a l l h o s t s ∗ ) port = ” 1234 ” ). 20 21 22 23 c o n f i g PSNonceCfg e x t e n d s NonceCfg ( s i z e = ”8” ). 24 25 26 t y p e d e f $PSNonce = Int@PSNonceCfg . 27 28 t y p e d e f $BobId = ConstStr@BobIdCfg . 29 30 31 t y p e d e f $Msg1 = ( $ I d e n t i f i e r , $PSNonce ) . Listing 10: Implemented first message: perrigsong.exdef 1 2 3 4 5 6 7 8 9 (∗ ∗ P e r r i g −Song m u t u a l a u t h e n t i c a t i o n p r o t o c o l ∗ ∗ h t t p : / /www . c s l . s r i . com/ u s e r s / m i l l e n / c a p s l / e x a m p l e s . h tm l ∗ h t t p : / / s p a r r o w . e c e . cmu . edu /˜ a d r i a n / p r o j e c t s / p r o t g e n −c s f w / c s f w . p d f ∗ eXpi v e r s i o n ∗ ∗ 1 . A−>B : ( a l i c e , Na ) ∗) 10 11 12 include ” . . / exdef / default . exdef ” include ” perrigsong . exdef ” 13 14 15 l e t pA = 5 16 17 18 ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) new Na : $PSNonce ; out ( c1 , ( a l i c e , Na ) ) . 19 20 21 22 23 24 l e t pB = ( ∗ l i s t e n t o c o n n e c t i o n s on c1 ∗ ) l e t c1 = a c c e p t [−>@ChanB ] ( c1 ) i n ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) i n ( c1 , ( name , Na ) ) . 25 26 27 free a l i c e : $ I d e n t i f i e r . 28 29 30 31 32 33 process new bob : $BobId ; ( ∗ c r e a t e common c o m m u n i c a t i o n c h a n n e l ∗ ) new c1 : Channel@ChanA<$Msg1 >; ( pA | pB ) Listing 11: Implemented first message: perrigsong.expi filename.expi Both files can be checked for errors by running expi2java with the --type-check (-t) flag: % ./expi2java -t testData/expi/perrigsong.expi -c -r parsing... OK type checking... OK inferring types... OK checking configuration... OK The flag --check-config (-c) is needed to also check that all types are configured correctly for code generation. 3.2 Second Message In the second message, Bob encrypts the received nonce together with a fresh nonce and his identity. Fortunately, the default set of configurations (see the “Configurations” Section of User Manual) already contains the configuration AES that has exactly the settings we need by default. We have already created the configurations for nonce and Bob’s identity, so the only part we still need to care about is the way we get the shared key. According to the informal specification, we store the key using the Java key store mechanism in the file key.store. The default library of cryptographic primitives and data structures provides a special channel configuration KeyStoreChCfg that can be used to retrieve the key. We extend the key store configuration in order to set up the file name. We also define a typedef for the key type, two typedefs for the key store channels and preliminary typedefs for message types (encrypted and plaintext): c o n f i g P SKeyStoreCfg e x t e n d s K e y S t o r e C h C f g ( k e y s t o r e f i l e n a m e = ” key . s t o r e ” , ). 6 t y p e d e f $PSKey = SymKey@AESKeyCfg<Top>. t y p e d e f $ P S K S t o r e R e q u e s t = Channel@PSKeyStoreCfg<Top>. ( ∗ t o s e n d a r e q u e s t ∗ ) t y p e d e f $PSKStoreAnswer = Channel@PSKeyStoreCfg<$PSKey >. ( ∗ t o r e c e i v e a k e y ∗ ) typedef $Msg2Plain t y p e d e f $Msg2 = Top . = SymEnc@AES<$Msg2Plain >. Listing 12: Key store configuration: perrigsong.exdef We set up the communication channels for the second message in the same way as for the first message: l e t pB = ( ∗ l i s t e n t o c o n n e c t i o n s on c1 ∗ ) l e t c1 = a c c e p t [−>@ChanB ] ( c1 ) i n l e t c2 = a c c e p t [−>@ChanB ] ( c2 ) i n l e t c3 = a c c e p t [−>@ChanB ] ( c3 ) i n ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) ... process ... ( ∗ c r e a t e common c o m m u n i c a t i o n c h a n n e l ∗ ) new c1 : Channel@ChanA<$Msg1 >; new c2 : Channel@ChanA<$Msg2 >; new c3 : Channel@ChanA<$Msg3 >; ( pA | pB ) Listing 13: Added remaining channels: perrigsong.expi We send a request for the key to the key store channel, receive a key, generate a fresh nonce and send the second message. We use the received identity to request the key, thus allowing Bob to communicate with other participants, as long as he has the corresponding key: l e t pB = ... i n ( c1 , ( name , Na ) ) ; ( ∗ g e t t h e s a v e d k e y f o r c o m m u n i c a t i o n wih A l i c e ∗ ) new k s r e q u e s t : $ P S K S t o r e R e q u e s t ; new k s a n s w e r : $PSKStoreAnswer ; out ( k s r e q u e s t , name ) ; i n ( k s a n s w e r , Kab ) ; ( ∗ Msg2 . B−>A : e n c ( ( Na , Nb , bob ) , K AB ) ∗ ) new Nb : $PSNonce ; out ( c2 , e n c ( ( Na , Nb , bob ) , Kab ) ) . Listing 14: Sent second message: perrigsong.expi Now we can change the $Msg2Plain typedef to the correct type: typedef $Msg2Plain = ( $PSNonce , $PSNonce , $BobId ) . Listing 15: Key store configuration: perrigsong.exdef In Alice’s process we first get the stored shared key for the communication with Bob in the same way as before, then receive the message, decrypt it and split the pairs: 7 l e t pA = ... out ( c1 , ( a l i c e , Na ) ) ; ( ∗ g e t t h e s a v e d k e y f o r c o m m u n i c a t i o n w i t h Bob ∗ ) new k s r e q u e s t : $ P S K S t o r e R e q u e s t ; new k s a n s w e r : $PSKStoreAnswer ; out ( k s r e q u e s t , bob ) ; i n ( k s a n s w e r , Kab ) ; ( ∗ Msg2 . B−>A : e n c ( ( Na , Nb , bob ) , K AB ) ∗ ) i n ( c2 , msg2 ) ; l e t ( Nx , Nb , name ) = d e c ( msg2 , Kab ) i n 0. Listing 16: Key store configuration: perrigsong.exdef Now Alice must check that the received name is “Bob” and the first nonce equals the one she sent to Bob in the first message, otherwise we abort the protocol: l e t pA = ... l e t ( Nx , Nb , name ) = d e c ( msg2 , Kab ) i n (∗ check r e c e i v e d data ∗) l e t ok = eq ( ( name , Nx ) , ( bob , Na ) ) i n 0. Listing 17: Checked received data: perrigsong.expi The result after implementing two messages is as follows: 1 2 3 (∗ ∗ P e r r i g −Song p r o t o c o l c o n f i g u r a t i o n ∗) 4 5 6 7 c o n f i g B o bIdCfg e x t e n d s A S C I I S t r i n g C f g ( message = ” bob ” ). 8 9 10 11 12 13 c o n f i g ChanA e x t e n d s T c p I p C h C f g ( ( ∗ c l i e n t ∗ ) variable = ”cA” , host = ” 1 2 7 . 0 . 0 . 1 ” , (∗ i p of the s e r v e r ∗) port = ” 1234 ” ). 14 15 16 17 18 19 c o n f i g ChanB e x t e n d s T c p I p C h C f g ( ( ∗ s e r v e r ∗ ) variable = ”cB” , host = ” any ” , ( ∗ l i s t e n s on a l l h o s t s ∗ ) port = ” 1234 ” ). 20 21 22 23 c o n f i g PSNonceCfg e x t e n d s NonceCfg ( s i z e = ”8” ). 24 25 26 27 c o n f i g P SKeyStoreCfg e x t e n d s K e y S t o r e C h C f g ( k e y s t o r e f i l e n a m e = ” key . s t o r e ” ). 28 29 8 30 t y p e d e f $PSNonce = Int@PSNonceCfg . 31 32 t y p e d e f $BobId = ConstStr@BobIdCfg . t y p e d e f $PSKey = SymKey@AES<Top>. 33 34 35 36 37 t y p e d e f $ P S K S t o r e R e q u e s t = Channel@PSKeyStoreCfg<Top>. ( ∗ t o s e n d a r e q u e s t ∗ ) t y p e d e f $PSKStoreAnswer = Channel@PSKeyStoreCfg<$PSKey >. ( ∗ t o r e c e i v e a k e y ∗ ) 38 39 40 41 42 43 44 typedef typedef typedef typedef typedef $Msg1 $Msg2Plain $Msg2 $Msg3Plain $Msg3 = = = = = ( $ I d e n t i f i e r , $PSNonce ) . ( $PSNonce , $PSNonce , $BobId ) . SymEnc@AES<$Msg2Plain >. Top . SymEnc@AES<$Msg3Plain >. Listing 18: Implemented second message: perrigsong.exdef 1 2 3 4 5 6 7 8 9 10 (∗ ∗ P e r r i g −Song m u t u a l a u t h e n t i c a t i o n p r o t o c o l ∗ ∗ h t t p : / /www . c s l . s r i . com/ u s e r s / m i l l e n / c a p s l / e x a m p l e s . h tm l ∗ h t t p : / / s p a r r o w . e c e . cmu . edu /˜ a d r i a n / p r o j e c t s / p r o t g e n −c s f w / c s f w . p d f ∗ eXpi v e r s i o n ∗ ∗ 1 . A−>B : ( a l i c e , Na ) ∗ 2 . B−>A : e n c ( ( Na , Nb , bob ) , Kab ) ∗) 11 12 13 include ” . . / exdef / default . exdef ” include ” perrigsong . exdef ” 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 l e t pA = ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) new Na : $PSNonce ; out ( c1 , ( a l i c e , Na ) ) ; ( ∗ g e t t h e s a v e d k e y f o r c o m m u n i c a t i o n wih Bob ∗ ) new k s r e q u e s t : $ P S K S t o r e R e q u e s t ; new k s a n s w e r : $PSKStoreAnswer ; out ( k s r e q u e s t , bob ) ; i n ( k s a n s w e r , Kab ) ; ( ∗ Msg2 . B−>A : e n c ( ( Na , Nb , bob ) , K AB ) ∗ ) i n ( c2 , msg2 ) ; l e t ( Nx , Nb , name ) = d e c ( msg2 , Kab ) i n (∗ check r e c e i v e d data ∗) l e t ok = eq ( ( name , Nx ) , ( bob , Na ) ) i n 0. 31 32 33 34 35 36 37 38 39 40 41 l e t pB = ( ∗ l i s t e n t o c o n n e c t i o n s on c1 ∗ ) l e t c1 = a c c e p t [−>@ChanB ] ( c1 ) i n l e t c2 = a c c e p t [−>@ChanB ] ( c2 ) i n l e t c3 = a c c e p t [−>@ChanB ] ( c3 ) i n ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) i n ( c1 , ( name , Na ) ) ; ( ∗ g e t t h e s a v e d k e y f o r c o m m u n i c a t i o n wih A l i c e ∗ ) new k s r e q u e s t : $ P S K S t o r e R e q u e s t ; new k s a n s w e r : $PSKStoreAnswer ; 9 42 43 44 45 46 47 out ( k s r e q u e s t , name ) ; i n ( k s a n s w e r , Kab ) ; ( ∗ Msg2 . B−>A : e n c ( ( Na , Nb , bob ) , K AB ) ∗ ) new Nb : $PSNonce ; out ( c2 , e n c ( ( Na , Nb , bob ) , Kab ) ) ; 0. 48 49 50 free a l i c e : $ I d e n t i f i e r . 51 52 53 54 55 56 57 58 process new bob : $BobId ; ( ∗ c r e a t e common c o m m u n i c a t i o n c h a n n e l ∗ ) new c1 : Channel@ChanA<$Msg1 >; new c2 : Channel@ChanA<$Msg2 >; new c3 : Channel@ChanA<$Msg3 >; ( pA | pB ) Listing 19: Implemented second message: perrigsong.expi 3.3 Third Message In third message, Alice encrypts the previously received nonce Nb together with the text message and sends them to Bob. We first need to prompt the user to enter the message and assign the entered text to a variable that we can then encrypt. In order to access the console, we use the channel configuration ConsoleChCfg and the corresponding typedefs $STDIN and $STDOUT. For the message type we will use String , since it is UTF-8 encoded by default. We extend the ConstStrCfg to define the prompt message and define the type that the third message is going to have: c o n f i g UserPrompt e x t e n d s C o n s t S t r C f g ( message = ” P l e a s e e n t e r t h e message : ” ) . t y p e d e f $PromptMsg = C o n s t S t r @ U s e r P r o m p t . typedef $Msg3Plain = ( $PSNonce , S t r i n g ) . Listing 20: Console configuration: perrigsong.exdef In Alice’s process, we set up the console channels, generate the prompt message, show it to the user and enter the message. Afterwards we complete Alice’s process by sending the third message: l e t pA = ... l e t ok = eq ( Nx , Na ) i n (∗ User i n t e r a c t i o n ∗) new c i n : $STDIN ; new c o u t : $STDOUT ; new prompt : $PromptMsg ; out ( cout , prompt ) ; i n ( c i n , message ) ; ( ∗ Msg3 . A−>B : e n c ( ( Nb , M) , Kab ) ∗ ) out ( c3 , e n c ( ( Nb , message ) , Kab ) ) . ... process 10 new bob : $BobId ; (∗ c o n s o l e c h a n n e l s ∗) new c i n : $STDIN ; new c o u t : $STDOUT ; ... Listing 21: Sent the third message: perrigsong.expi In Bob’s process, we receive the message, decrypt it, split the resulting pair, check that the received nonce equals the one just sent and display the message to the user: l e t pB = ... ( ∗ Msg3 . A−>B : e n c ( ( Nb , M) , Kab ) ∗ ) i n ( c3 , msg3 ) ; l e t ( Nx , message ) = d e c ( msg3 , Kab ) i n l e t ok = eq ( Nx , Nb ) i n ( ∗ show t h e r e c e i v e d message ∗ ) out ( cout , message ) . Listing 22: Received the third message: perrigsong.expi Finally, we get the complete implementation of the Perrig-Song mutual authentication protocol in Extensible Spi Calculus: 1 2 3 (∗ ∗ P e r r i g −Song p r o t o c o l c o n f i g u r a t i o n ∗) 4 5 6 7 c o n f i g B o bIdCfg e x t e n d s A S C I I S t r i n g C f g ( message = ” bob ” ). 8 9 10 11 12 13 c o n f i g ChanA e x t e n d s T c p I p C h C f g ( ( ∗ c l i e n t ∗ ) variable = ”cA” , host = ” 1 2 7 . 0 . 0 . 1 ” , (∗ i p of the s e r v e r ∗) port = ” 1234 ” ). 14 15 16 17 18 19 c o n f i g ChanB e x t e n d s T c p I p C h C f g ( ( ∗ s e r v e r ∗ ) variable = ”cB” , host = ” any ” , ( ∗ l i s t e n s on a l l h o s t s ∗ ) port = ” 1234 ” ). 20 21 22 23 c o n f i g PSNonceCfg e x t e n d s NonceCfg ( s i z e = ”8” ). 24 25 26 27 c o n f i g P SKeyStoreCfg e x t e n d s K e y S t o r e C h C f g ( k e y s t o r e f i l e n a m e = ” key . s t o r e ” ). 28 29 30 t y p e d e f $PSNonce = Int@PSNonceCfg . 31 32 t y p e d e f $BobId = ConstStr@BobIdCfg . 33 11 34 t y p e d e f $PSKey = SymKey@AES<Top>. 35 36 37 t y p e d e f $ P S K S t o r e R e q u e s t = Channel@PSKeyStoreCfg<Top>. ( ∗ t o s e n d a r e q u e s t ∗ ) t y p e d e f $PSKStoreAnswer = Channel@PSKeyStoreCfg<$PSKey >. ( ∗ t o r e c e i v e a k e y ∗ ) 38 39 40 c o n f i g UserPrompt e x t e n d s C o n s t S t r C f g ( message = ” P l e a s e e n t e r t h e message : ” ) . t y p e d e f $PromptMsg = C o n s t S t r @ U s e r P r o m p t . 41 42 43 44 45 46 typedef typedef typedef typedef typedef $Msg1 $Msg2Plain $Msg2 $Msg3Plain $Msg3 = = = = = ( $ I d e n t i f i e r , $PSNonce ) . ( $PSNonce , $PSNonce , $BobId ) . SymEnc@AES<$Msg2Plain >. ( $PSNonce , S t r i n g ) . SymEnc@AES<$Msg3Plain >. Listing 23: Perrig-Song mutual authentication protocol: perrigsong.exdef 1 2 3 4 5 6 7 8 9 10 11 (∗ ∗ P e r r i g −Song m u t u a l a u t h e n t i c a t i o n p r o t o c o l ∗ ∗ h t t p : / /www . c s l . s r i . com/ u s e r s / m i l l e n / c a p s l / e x a m p l e s . h tm l ∗ h t t p : / / s p a r r o w . e c e . cmu . edu /˜ a d r i a n / p r o j e c t s / p r o t g e n −c s f w / c s f w . p d f ∗ eXpi v e r s i o n ∗ ∗ 1 . A−>B : ( a l i c e , Na ) ∗ 2 . B−>A : e n c ( ( Na , Nb , bob ) , Kab ) ∗ 3 . A−>B : e n c ( ( Nb , message ) , Kab ) ∗) 12 13 14 include ” . . / exdef / default . exdef ” include ” perrigsong . exdef ” 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 l e t pA = ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) new Na : $PSNonce ; out ( c1 , ( a l i c e , Na ) ) ; ( ∗ g e t t h e s a v e d k e y f o r c o m m u n i c a t i o n wih Bob ∗ ) new k s r e q u e s t : $ P S K S t o r e R e q u e s t ; new k s a n s w e r : $PSKStoreAnswer ; out ( k s r e q u e s t , bob ) ; i n ( k s a n s w e r , Kab ) ; ( ∗ Msg2 . B−>A : e n c ( ( Na , Nb , bob ) , K AB ) ∗ ) i n ( c2 , msg2 ) ; l e t ( Nx , Nb , name ) = d e c ( msg2 , Kab ) i n (∗ check r e c e i v e d data ∗) l e t ok = eq ( ( name , Nx ) , ( bob , Na ) ) i n (∗ User i n t e r a c t i o n ∗) new prompt : $PromptMsg ; out ( cout , prompt ) ; i n ( c i n , message ) ; ( ∗ Msg3 . A−>B : e n c ( ( Nb , M) , Kab ) ∗ ) out ( c3 , e n c ( ( Nb , message ) , Kab ) ) . 37 38 39 40 41 42 43 l e t pB = ( ∗ l i s t e n t o c o n n e c t i o n s on c1 ∗ ) l e t c1 = a c c e p t [−>@ChanB ] ( c1 ) i n l e t c2 = a c c e p t [−>@ChanB ] ( c2 ) i n l e t c3 = a c c e p t [−>@ChanB ] ( c3 ) i n ( ∗ Msg1 . A−>B : ( a l i c e , Na ) ∗ ) 12 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 i n ( c1 , ( name , Na ) ) ; ( ∗ g e t t h e s a v e d k e y f o r c o m m u n i c a t i o n wih A l i c e ∗ ) new k s r e q u e s t : $ P S K S t o r e R e q u e s t ; new k s a n s w e r : $PSKStoreAnswer ; out ( k s r e q u e s t , name ) ; i n ( k s a n s w e r , Kab ) ; ( ∗ Msg2 . B−>A : e n c ( ( Na , Nb , bob ) , K AB ) ∗ ) new Nb : $PSNonce ; out ( c2 , e n c ( ( Na , Nb , bob ) , Kab ) ) ; ( ∗ Msg3 . A−>B : e n c ( ( Nb , M) , Kab ) ∗ ) i n ( c3 , msg3 ) ; l e t ( Nx , message ) = d e c ( msg3 , Kab ) i n l e t ok = eq ( Nx , Nb ) i n ( ∗ show t h e r e c e i v e d message ∗ ) out ( cout , message ) . 59 60 61 free a l i c e : $ I d e n t i f i e r . 62 63 64 65 66 67 68 69 70 71 72 process new bob : $BobId ; (∗ c o n s o l e c h a n n e l s ∗) new c i n : $STDIN ; new c o u t : $STDOUT ; ( ∗ c r e a t e common c o m m u n i c a t i o n c h a n n e l ∗ ) new c1 : Channel@ChanA<$Msg1 >; new c2 : Channel@ChanA<$Msg2 >; new c3 : Channel@ChanA<$Msg3 >; ( pA | pB ) Listing 24: Perrig-Song mutual authentication protocol: perrigsong.expi 4 Code Generation The code generation step is automated, only some configuration options must be specified by the user. We will use the testCode/expi2java/perrigsong directory as the target directory, and “perrigsong” as the package name. The implementation class will be called “PerrigSong”. We will use the default code templates in data/expi2java/javaTemplates and no additional imports, since we do not use any additional implementation classes. In addition, the output directory must be created first. This results in the following calls: % mkdir testCode/expi2java/perrigsong % ./expi2java -g testData/expi/perrigsong.expi \ -p perrigsong \ -m data/expi2java/javaTemplates \ -o testCode/expi2java/perrigsong \ -n "PerrigSong" parsing... OK type checking... OK inferring types... OK checking configuration... OK generating code... OK 13 Since we decided to use a free name for the Alice’s identity in Section 3.1, we need to initialize all free names in the generated code. We go to the code directory and open the file perrigsong/Application.java and search for the word “FIXME”. In the lines 102-103 we find the following code: // FIXME a l l f r e e names a r e u s e r −p r o v i d e d , I d e n t i f i e r alice 139 = null ; i n i t i a l i z e and f i n a l i z e them . . . Listing 25: Generated perrigsong/Application.java We change it to: Identifier a l i c e 1 3 9 = new I d e n t i f i e r ( ” a l i c e ” ) ; Listing 26: Initialized free names in perrigsong/Application.java Now we need to compile the generated code. We set the class path to contain the library and the Bouncy Castle Provider Jar file and run the compiler: % cd testCode/expi2java % CLASSPATH=".:../../bin/eXpiLibrary.jar:../../lib/bcprov-jdk16-141.jar" % javac perrigsong/*.java Now we can start the generated test application: % java perrigsong.Application --help eXpi2Java protocol test - Run the generated PerrigSong protocol USAGE: -h [options] OPTIONS: -h, --help -d, --debug --show -k <name> <config> --keygen <name> <config> : Print this help : Enable debug modus : Show the content of the keystore (buggy) : Generate a new symmetric key, store it under this name and exit -c <from> <to> <config> --copy-key <from> <to> <config> : Copy a symmetric key stored under the name <from> as <to> and exit -p <name> --participant <name> : Only run code for this participant <name> can be on of: pA, pB The default test application offer several options. If started without parameters, it runs both participants in parallel, to run only one of the participants, the option --participant can be used. With --debug, some additional information about the protocol progress is shown. With --keygen and --copy-key, we can modify the contents of a key store. 14 Since the Perrig-Song protocol relies on the known shared key, we first need to create it and store it in the key store: % java perrigsong.Application -k alice AESKeyCfg % java perrigsong.Application -c alice bob AESKeyCfg % ls jce* jce.keystore % mv jce.keystore key.store % ls key* key.store Note that jce.keystore is used as the key store filename by default and we need to rename it first to match our settings. Now we can finally test the generated protocol. We open another shell, go to the code directory, set up the class path as before and start the server: % cd testCode/expi2java % CLASSPATH=".:../../bin/eXpiLibrary.jar:../../lib/bcprov-jdk16-141.jar" % java perrigsong.Application -p pB In the previous shell, we start the client, after some short time, a prompt should appear. We enter the message “’Hello!!!’ and press enter: % java perrigsong.Application -p pA Please enter the message: Hello!!! This message should be printed on the shell where the server is running, then both programs should terminate: % java perrigsong.Application -p pB Hello!!! References [MM01] J. Millen and F. Muller. Cryptographic protocol generation from CAPSL. Technical Report SRI-CSL-01-07, SRI International, December 2001. 1 List of Figures 1 Perrig-Song mutual authentication protocol . . . . . . . . . . . . . . . . . . . . . 15 1 Listings 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Simple setup: perrigsong.expi . . . . . . . . . . . . . . . . . . Simple setup: perrigsong.exdef . . . . . . . . . . . . . . . . . . Added Alice’s identity: perrigsong.expi . . . . . . . . . . . . . Added BobIdCfg: perrigsong.exdef . . . . . . . . . . . . . . . . Added Bob’s identity: perrigsong.expi . . . . . . . . . . . . . . Channel configurations: perrigsong.exdef . . . . . . . . . . . . Created a common channel: perrigsong.expi . . . . . . . . . . Nonce configuration: perrigsong.exdef . . . . . . . . . . . . . . First message: perrigsong.expi . . . . . . . . . . . . . . . . . . Implemented first message: perrigsong.exdef . . . . . . . . . . Implemented first message: perrigsong.expi . . . . . . . . . . . Key store configuration: perrigsong.exdef . . . . . . . . . . . . Added remaining channels: perrigsong.expi . . . . . . . . . . . Sent second message: perrigsong.expi . . . . . . . . . . . . . . Key store configuration: perrigsong.exdef . . . . . . . . . . . . Key store configuration: perrigsong.exdef . . . . . . . . . . . . Checked received data: perrigsong.expi . . . . . . . . . . . . . Implemented second message: perrigsong.exdef . . . . . . . . . Implemented second message: perrigsong.expi . . . . . . . . . Console configuration: perrigsong.exdef . . . . . . . . . . . . . Sent the third message: perrigsong.expi . . . . . . . . . . . . . Received the third message: perrigsong.expi . . . . . . . . . . Perrig-Song mutual authentication protocol: perrigsong.exdef Perrig-Song mutual authentication protocol: perrigsong.expi . Generated perrigsong/Application.java . . . . . . . . . . . . Initialized free names in perrigsong/Application.java . . . . 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 3 3 3 3 4 4 4 4 5 5 6 7 7 7 8 8 8 9 10 10 11 11 12 14 14