OpenFIPS201 icon indicating copy to clipboard operation
OpenFIPS201 copied to clipboard

Provisioning card without secure channel

Open mistial-dev opened this issue 1 year ago • 7 comments

I'm working on some unit testing for use with OpenFIPS201, and am using jCardSim. The open source version does not support Global Platform or Secure Channel.

Looking through the code, I can see that administrative keys can be used for card administration, but I do not see a way to create an administrator key without using a secure channel.

Does the administrative user have to be defined in secure channel before it can be used for other operations?

mistial-dev avatar Sep 26 '23 21:09 mistial-dev

Hi @mistial-dev, yes this is correct there is no way to avoid SCP at all in this case for a few reasons:

  • The file system must first be defined (since the existence of the '9B' key is just a configuration item for OF201)
  • Because of the above, default values aren't in place. This is further restricted by FIPS 140 which states that any default authentication data must be replaced on first use. There isn't an elegant solution to enforce this, though it's possible.
  • We have explicitly never permitted key material to be sent over plaintext, and again FIPS 140 cements this requirement by prohibiting it.

Philosophically speaking, we don't encourage the 9B key at all since it provides no encryption or integrity for the subsequent management commands. It is retained for backwards-compatibility, but as you have seen it really only helps you post-issuance.

I ran into the same issue with testing as you have. It is unfortunate that jCardSim doesn't support it but hey they have to make money somehow in a pretty niche market so I can't totally blame them :)

Our unit testing was all inside an old commercial tool and I tried a few different approaches, but ultimately the testing framework became Zephyr Scale (on JIRA) to define the tests generically and then export them to NXP JCShell scripts. This gave us SCP support ability to easily use the P71D600 simulator (which helps with FIPS testing).

It's a good tool, but I'm not happy that it is proprietary and requires an NXP NDA and a few hoops to get! The Zephyr Scale aspect gives the option to de-couple from this when a good solution is found/developed and one day we will, but for now it's a pragmatic option for testing.

makinako avatar Sep 27 '23 05:09 makinako

Looking at the use of GPSystem in this applet (GPSystem.getSecureChannel(), resetSecurity(), getSecurityLevel(), unwrap(), processSecurity()) then "mocking" this as a java code for jcardsim is max half day of effort. Don't know about CVM but probably the same.

martinpaljak avatar Sep 27 '23 05:09 martinpaljak

Looking at the use of GPSystem in this applet (GPSystem.getSecureChannel(), resetSecurity(), getSecurityLevel(), unwrap(), processSecurity()) then "mocking" this as a java code for jcardsim is max half day of effort. Don't know about CVM but probably the same.

It's true, but only if we had a Java implementation of SCP to base it off :) For the accreditation process we are locked into the current JCShell path but if we had this available for JCardSim it would be a logical next step for the generic tests (Which are most of them)

makinako avatar Sep 28 '23 06:09 makinako

Looking at the use of GPSystem in this applet (GPSystem.getSecureChannel(), resetSecurity(), getSecurityLevel(), unwrap(), processSecurity()) then "mocking" this as a java code for jcardsim is max half day of effort. Don't know about CVM but probably the same.

I put around that much time into trying to get mocking working before asking about alternate ways. I’m not an expert Java developer, and the techniques I use in dot net don’t really translate well. jCardSim seems to want a class, and mocking synthesizes a new class. I got as far as extracting the instantiated class from the jCardSim runtime, to use with the mocking framework, but then had no way to feed it back into jCardSim.

My plan was to just make a fake security domain that would pass through APDUs untouched. That way I could keep my Gpshell scripts otherwise unmodified.

mistial-dev avatar Sep 28 '23 06:09 mistial-dev

ChatGPT proved surprisingly helpful.

    @org.junit.jupiter.api.Test
    void testConfiguration() {
        try (MockedStatic<GPSystem> mocked = Mockito.mockStatic(GPSystem.class)) {
            SecureChannel mockedSecureChannel = Mockito.mock(SecureChannel.class);

            // Mock getSecurityLevel() to return a value that indicates that the card is authenticated, has decryption, and has MAC
            Mockito.when(mockedSecureChannel.getSecurityLevel()).thenReturn((byte) (SecureChannel.AUTHENTICATED | SecureChannel.C_DECRYPTION | SecureChannel.C_MAC));

            // Mock getSecureChannel() to return the mocked SecureChannel
            mocked.when(GPSystem::getSecureChannel).thenReturn(mockedSecureChannel);

            // Mock `short processSecurity(APDU apdu)` to return 0 bytes of data.
            Mockito.when(mockedSecureChannel.processSecurity(Mockito.any())).thenReturn((short)0);
            
            // Mock `short unwrap(byte[] data, short offset, short length)` to return the length (from the third argument)
            Mockito.when(mockedSecureChannel.unwrap(Mockito.any(byte[].class), Mockito.anyShort(), Mockito.anyShort())).thenAnswer(invocation -> invocation.getArgument(2));

            // Check for a success response
            byte[] dataBytes = simulator.selectAppletWithResult(OF201_AID);

            // The last two bytes of the response should be 0x9000.  Verify that.
            assertArrayEquals(new byte[]{(byte) 0x90, (byte) 0x00}, new byte[]{dataBytes[dataBytes.length - 2], dataBytes[dataBytes.length - 1]});

            // Define the configuration command in hex
            String configurationCommand = "E4 DB 3F 00 5D 68 5B A0 24 80 01 FF 81 01 00 82 01 00 83 01 00 84 01 06 85 01 08 86 01 06 87 01 " +
                    "05 88 01 00 89 01 04 8A 01 00 8B 01 00 A1 12 80 01 FF 81 01 00 82 01 08 83 01 06 84 01 05 85 01 " +
                    "00 A2 03 80 01 00 A3 03 80 01 00 A4 15 80 01 00 81 01 00 82 01 00 83 01 00 84 01 FF 85 01 00 86 " +
                    "01 00";

            // Execute the configuration command and get the response
            CommandAPDU configurationCommandAPDU = new CommandAPDU(hexStringToByteArray(configurationCommand));
            ResponseAPDU configurationResponseAPDU = simulator.transmitCommand(configurationCommandAPDU);

            // Verify that the response is 0x9000
            assertArrayEquals(new byte[]{(byte) 0x90, (byte) 0x00}, configurationResponseAPDU.getBytes());
        }
    }

mistial-dev avatar Sep 28 '23 08:09 mistial-dev

ChatGPT proved surprisingly helpful.

I wonder whose code that is, and which license it was under.

no-usernames-left avatar Jul 09 '24 14:07 no-usernames-left

I wonder whose code that is, and which license it was under.

Much of it likely is derived from the Mokito documentation, or the GlobalPlatform documentation (which has its own license, but is likely not relevant given that the use is functional, rather than creative). The Mokito library itself (which may be where some of the training is from) is MIT.

Much of it is extremely formulaic and functional, and was guided prompting. It wasn't like someone had written similar code that was just prompted.

As an example, when I asked it to mock processSecurity to return 0 bytes of data, it picked the most logical and straightforward way to do it. The comments are mine, and were used for the prompting.

            // Mock `short processSecurity(APDU apdu)` to return 0 bytes of data.
            Mockito.when(mockedSecureChannel.processSecurity(Mockito.any())).thenReturn((short)0);

It's similar to the phonebook - you can't copyright a phone number, only the creative aspects of an arrangement of phone numbers. The choice of what to mock, how to mock it, why to mock it, representation of the data (in hex), the command that was run, and the response was all mine. In other words, the creative elements.

So, if you want to know "whose code that is", it's mine, because the elements that are copyrightable are mine.

mistial-dev avatar Jul 18 '24 01:07 mistial-dev