9 Replies Latest reply: Jun 8, 2012 4:06 AM by 941427 RSS

    can't generate the correct session keys for mutual authentification

    941427
      Hi,

      I'm working on mutual authentification process using SCP02 of global plateform and i can't generate the correct session keys . here is my process in java

      kmc="52554E4E43415244454E53494341454E"

      private static byte[] Static_ENC_key={0x27,(byte) 0x28,(byte)0x37,(byte) 0x34,(byte) 0x03,(byte) 0xD9,(byte) 0x90,(byte) 0xBD,(byte) 0xA5,(byte) 0x0F,
                (byte) 0xFC,(byte) 0x8F,(byte) 0x65,(byte) 0xF8,(byte) 0xAC,(byte) 0x21};

      private static byte[] Static_MAC_key={(byte) 0x38,0x53,(byte)0x66,(byte) 0x85,(byte) 0xE3,(byte) 0xBB,(byte) 0xF9,(byte) 0xFA,(byte) 0xE7,
                               (byte) 0x41,(byte) 0x9D,(byte) 0x89,(byte) 0xDB,(byte) 0xAE,(byte) 0x22,(byte) 0xE0};

      byte[] sequence_counter={0x00,0x05};
                byte[] card_challenge={(byte) 0x9C,(byte) 0xB0,0x21,(byte) 0x99,0x67,0x18};
                byte[] card_cryptogram={(byte) 0xEE,0x69,(byte) 0xEE,0x05,0x3A,0x04,0x4E,0x2F};
                
           byte[] padding={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
                
                //for S-ENC
                byte[] derivation_data_enc=new byte [16];
                byte[] constant_enc={0x01,(byte) 0x82};
                System.arraycopy(constant_enc,0,derivation_data_enc,0,constant_enc.length);
                System.arraycopy(sequence_counter,0,derivation_data_enc,constant_enc.length,sequence_counter.length);
                System.arraycopy(padding,0,derivation_data_enc,sequence_counter.length+constant_enc.length,padding.length);
           
                //for S-MAC
                byte[] derivation_data_mac=new byte [16];
                byte[] constant_mac={0x01,(byte) 0x01};
                System.arraycopy(constant_mac,0,derivation_data_mac,0,constant_mac.length);
                System.arraycopy(sequence_counter,0,derivation_data_mac,constant_mac.length,sequence_counter.length);
                System.arraycopy(padding,0,derivation_data_mac,sequence_counter.length+constant_mac.length,padding.length);
           
                
                
                //create a 3DES key from static ENC key
                DESedeKeySpec key_deriv = new DESedeKeySpec(Apdu.ba2s(Static_ENC_key).getBytes());
                SecretKeyFactory key_factory=SecretKeyFactory.getInstance("DESede");
                javax.crypto.SecretKey key_enc = key_factory.generateSecret(key_deriv);

           //create a 3DES key from static MAC key
                DESedeKeySpec key_deriv1 = new DESedeKeySpec(Apdu.ba2s(Static_MAC_key).getBytes());
                SecretKeyFactory key_factory1=SecretKeyFactory.getInstance("DESede");
                javax.crypto.SecretKey key_mac = key_factory1.generateSecret(key_deriv1);
                
                IvParameterSpec iv = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0});
                
                
                
                /*******************Generation of ENC and MAC session key according to SCP02*************/
                try {
                     
                     Cipher cipherCBC_enc = Cipher.getInstance("DESede/CBC/noPadding");
                     
                     //create Kenc
                     cipherCBC_enc.init(Cipher.ENCRYPT_MODE,key_enc,iv);
                     byte[] Session_S_ENC_key=cipherCBC_enc.doFinal(derivation_data_enc);     
                     
                     System.out.println("S-ENC Session Key"+Apdu.ba2s(Session_S_ENC_key));
                     //create Kmac
                     cipherCBC_enc.init(Cipher.ENCRYPT_MODE,key_mac,iv);
                     byte[] Session_S_MAC_key=cipherCBC_enc .doFinal(derivation_data_mac);     
                     System.out.println("S-MAC Session Key"+Apdu.ba2s(Session_S_MAC_key));
                     
                     
                } catch (IllegalBlockSizeException e) {     
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                } catch (BadPaddingException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                }
                catch (InvalidKeyException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                }               
                
      i got S-ENC Session Key16: 83D00FEB8EF10A3A121CCD6E3AD9801F
      S-MAC Session Key16: 06F56718AD5E029E67C7913F87C90FD0

      But the correct one is
      S-ENC Session Key: F6371CEB27A62FB944C4DDC1A2E52E70

      Please help, i can't move to verifying the card crypto until i get the correct keys
        • 1. Re: can't generate the correct session keys for mutual authentification
          Sebastien_Lorquet
          this crypto is not a trivial piece of work, it requires very careful inspection of the gp spec. Everything is written in there. the only other document required is the way to compute the ISO9697 (IIRC) HMAC. single DES rounds plus final triple des is tricky. (maybe it's for SCP01? can't remember, I implemented both, because I also have old cards - that was 3 years ago)

          Anyway it's normal to spend a large amount of time on it.

          are you sure that you used the same challenges and sequence counter?
          also check the IVParameterSpec is not passed by reference so the iv may be modified between the two uses.
          and check the chaining mode, I remember ECB and CBC are used, I may be confused wit SCP01

          and double check all constants, I don't have the spec under my nose right now but I remember there was a 0181 somewhere, maybe not 0182.

          All of this from memory of course, that's just some ways to go forward. this needs to be fact checked with the proper documents.
          • 2. Re: can't generate the correct session keys for mutual authentification
            941427
            I'm using the SCP02 conforming to the GPCardSpec_v2.2 , and for the generation of th EN key session the constant is 0182, 0181 is for KEK session key. For the ecryption mode it's the CBC one i cheked on the spec. But fir the IV i don't get it, you say 'is not passed by reference' , because first i initialize it and pass it in the method init directly.

            In the spec the way we obtain the derivation data for SCP02 is constant+sequence counter+padding (0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00).

            I think the problem is the way i encrypt or i don't khwo because i'm using DESedeKeySpec for the instantiation of the key and SecretKeyFactory . Do you think this implementation is the problem???

            NB: i'm using the information of anathor test that was succesful in external authentificate , so i used the same keys and the same card response f0r init update just to obtain the correct session key.
            • 3. Re: can't generate the correct session keys for mutual authentification
              Sebastien_Lorquet
              okay

              if you have doubts about crypto, you can use bouncycastle. instead of using normal java crypto api, this lib has direct crypto routines that are simpler to use
              See the following classes:

              import org.bouncycastle.crypto.BlockCipher;
              import org.bouncycastle.crypto.digests.SHA1Digest; //nothing to do with gp!
              import org.bouncycastle.crypto.digests.SHA256Digest;
              import org.bouncycastle.crypto.engines.DESEngine;
              import org.bouncycastle.crypto.engines.DESedeEngine;
              import org.bouncycastle.crypto.modes.CBCBlockCipher;
              import org.bouncycastle.crypto.params.KeyParameter;
              import org.bouncycastle.crypto.params.ParametersWithIV;


              the thing with the iv was: are you sure the iv is correctly initialized each time you use it in cipher.init()?

              it could happen that the data inside the iv array is modified after being used in init/update/dofinal, to allow continuation of the crypto stream in next calls. displaying the value of "iv" just before use could help.
              • 4. Re: can't generate the correct session keys for mutual authentification
                Adriaan
                For a good working example, look at the GPJ source code: http://sourceforge.net/projects/gpj/
                • 5. Re: can't generate the correct session keys for mutual authentification
                  941427
                  thank a lot i used the boucy castle API and i got the good key.
                  • 6. Re: can't generate the correct session keys for mutual authentification
                    941427
                    i can't find import org.bouncycastle.crypto.modes.ECBBlockCipher . i need to encrypt with ECB mode but eclipse can't resolve it , knowing that it recognize all other importations.

                    Thankx,
                    • 7. Re: can't generate the correct session keys for mutual authentification
                      Sebastien_Lorquet
                      yes, there is no class for ECB, because Electronic Code*B*ook is the trivial mode.
                      On the contrary CBC is an additional "layer" (mode of operation) that can work with any block algorithm, so a helper class was made for it.

                      Just encode the input blocks with DESedeEngine with the same key without any chaining.

                      If you're implementing a spec that uses ECB that's ok, but for anything else (including large data blocks) it's not very secure. Just see the wikipedia article and compare the tux images!

                      http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation


                      I'm glad that I could help.

                      Regards

                      (PS: @Adriaan "a fishing pole is better that a fish", looking at someone else's code is not a good way to build expertise - you may loose time, copy hidden bugs, and loose freedom to implement it in a way that you control and understand - specifically such a crypto code. going back to the spec is the best way to learn here. If you want to check you work, generate test vectors with a known good implementation and compare. in that situation, the test vectors were already made by our "numbered" friend)
                      • 8. Re: can't generate the correct session keys for mutual authentification
                        941427
                        Thank you very match!! it works just with DESedeEngine(). I have to say that the bouncy castle API is very efficient, i didn't expect that !
                        • 9. Re: can't generate the correct session keys for mutual authentification
                          941427
                          Hi,

                          I have a strange problem that i can't understand.I'm testing the mutual authentification process,so i have already a test that succeded but not in my application.So when i take information for the response of the card to init update (i mean sequence counter , data diversification , card challenge and cart cryptogram) i get the good session keys , card cryptogram and MAC when i compare to the result of the other test .But!! when i use another test with another information , it failed !!! I can't understand

                          Please help if you have an idea about the reason of this problem

                          Thankx