diff --git a/pytools/gpgcard/gpgcard.py b/pytools/gpgcard/gpgcard.py index eaf9109..39a761c 100644 --- a/pytools/gpgcard/gpgcard.py +++ b/pytools/gpgcard/gpgcard.py @@ -109,6 +109,7 @@ class GPGCard() : if device.startswith("ledger:"): self.token = getDongle(True) self.exchange = self._exchange_ledger + self.disconnect = self._disconnect_ledger elif device.startswith("pcsc:"): allreaders = readers() for r in allreaders: @@ -120,6 +121,7 @@ class GPGCard() : self.connection = r.createConnection() self.connection.connect() self.exchange = self._exchange_pcsc + self.disconnect = self._disconnect_pcsc else: #print("No") pass @@ -127,6 +129,8 @@ class GPGCard() : print("No token") + + ### APDU interface ### def _exchange_ledger(self,cmd,sw=0x9000): resp = b'' @@ -159,6 +163,14 @@ class GPGCard() : sw = (sw1<<8)|sw2 #print("xch S resp: %s %.04x"%(binascii.hexlify(resp),sw)) return resp,sw + + def _disconnect_ledger(self): + return self.token.close() + + def _disconnect_pcsc(self): + r = self.connection.disconnect() + #self.connection.releaseContext() + return r def select(self): apdu = binascii.unhexlify(b"00A4040006D27600012401") diff --git a/sdk/usbd_ccid_if.c b/sdk/usbd_ccid_if.c index fd07035..b212737 100644 --- a/sdk/usbd_ccid_if.c +++ b/sdk/usbd_ccid_if.c @@ -513,7 +513,7 @@ uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter, case 0: // verify pin //ret_len = dwLength - 15; ret_len = 5; - os_memmove(G_io_apdu_buffer, pbuf+15, 5); + off = 15; break; case 1: // modify pin @@ -531,7 +531,6 @@ uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter, } //ret_len = dwLength - off; ret_len = 5; - os_memmove(G_io_apdu_buffer, pbuf+off, 5); break; default: // unsupported @@ -540,7 +539,9 @@ uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter, CCID_Send_Reply(&USBD_Device); return SLOTERROR_CMD_NOT_SUPPORTED; } - return SC_XferBlock(G_io_apdu_buffer, ret_len, &ret_len); + pbuf += off; + pbuf[0] = 0xEF; + return SC_XferBlock(pbuf, ret_len, &ret_len); } // prepare the apdu to be processed by the application diff --git a/src/gpg_data.c b/src/gpg_data.c index f4e5905..2c1ac08 100644 --- a/src/gpg_data.c +++ b/src/gpg_data.c @@ -654,10 +654,27 @@ int gpg_apdu_put_data(unsigned int ref) { } /* ----------------- RC ----------------- */ - case 0xD3: - sw = gpg_apdu_change_ref_data(); - break; + case 0xD3: { + gpg_pin_t *pin; + pin = gpg_pin_get_pin(PIN_ID_RC); + if (G_gpg_vstate.io_length == 0) { + gpg_nvm_write(pin, NULL, sizeof(gpg_pin_t)); + + } + else if ((G_gpg_vstate.io_length > GPG_MAX_PW_LENGTH) || + (G_gpg_vstate.io_length < 8)) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } else { + gpg_pin_set(pin, + G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, + G_gpg_vstate.io_length); + } + sw = SW_OK; + break; + } + /* ----------------- UIF ----------------- */ case 0xD6: ptr_v = G_gpg_vstate.kslot->sig.UIF; diff --git a/src/gpg_dispatch.c b/src/gpg_dispatch.c index 0bc7cc9..6e907b3 100644 --- a/src/gpg_dispatch.c +++ b/src/gpg_dispatch.c @@ -236,7 +236,7 @@ int gpg_dispatch() { unsigned int tag,t,l; int sw; - if ((G_gpg_vstate.io_cla != 0x00) && (G_gpg_vstate.io_cla != 0x10)) { + if ((G_gpg_vstate.io_cla != 0x00) && (G_gpg_vstate.io_cla != 0x10) && (G_gpg_vstate.io_cla != 0xEF)) { THROW(SW_CLA_NOT_SUPPORTED); return SW_CLA_NOT_SUPPORTED; } @@ -271,7 +271,6 @@ int gpg_dispatch() { } - /* Other commands allowed if not terminated */ if (N_gpg_pstate->histo[7] != 0x07) { THROW(SW_STATE_TERMINATED); diff --git a/src/gpg_init.c b/src/gpg_init.c index 8aca2f7..03207b1 100644 --- a/src/gpg_init.c +++ b/src/gpg_init.c @@ -92,7 +92,7 @@ int gpg_oid2curve(unsigned char* oid, unsigned int len) { /* -------------------------------*/ const unsigned char C_ext_capabilities[10] = { - //-SM, +getchallenge, +keyimport, +PWchangeable, +privateDO, +algAttrChangeable, +AES, -RFU + //-SM, +getchallenge, +keyimport, +PWchangeable, +privateDO, +algAttrChangeable, +AES, -KDF 0x7E, // No SM, 0x00, @@ -104,8 +104,8 @@ const unsigned char C_ext_capabilities[10] = { SHORT(GPG_EXT_PRIVATE_DO_LENGTH), //PIN block formart 2 not supported 0x00, - //RFU - 0x00 + //MSE + 0x01 }; diff --git a/src/gpg_io.c b/src/gpg_io.c index 50a46cf..4fa85b1 100644 --- a/src/gpg_io.c +++ b/src/gpg_io.c @@ -247,7 +247,7 @@ int gpg_io_fetch(unsigned char* buffer, int len) { int gpg_io_do(unsigned int io_flags) { //if pending input chaining - if (G_gpg_vstate.io_cla & 0x01) { + if (G_gpg_vstate.io_cla & 0x10) { goto in_chaining; } diff --git a/src/gpg_mse.c b/src/gpg_mse.c new file mode 100644 index 0000000..d3cc88c --- /dev/null +++ b/src/gpg_mse.c @@ -0,0 +1,78 @@ +/* Copyright 2017 Cedric Mesnil , Ledger SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "os.h" +#include "cx.h" +#include "gpg_types.h" +#include "gpg_api.h" +#include "gpg_vars.h" + +static int gpg_mse_set(int crt, int ref) { + + if (crt == 0xA4) { + if (ref == 0x02) { + G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->dec; + } + if (ref == 0x03) { + G_gpg_vstate.mse_aut = &G_gpg_vstate.kslot->aut; + } + } + + if (crt == 0xB8) { + if (ref == 0x02) { + G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->dec; + } + if (ref == 0x03) { + G_gpg_vstate.mse_dec = &G_gpg_vstate.kslot->aut; + } + } + return 0; +} + + + +int gpg_mse_reset() { + gpg_mse_set(0xA4, 0x03); + gpg_mse_set(0xB8, 0x02); + return 0; +} + +int gpg_apdu_mse() { + int crt,ref; + + + if ((G_gpg_vstate.io_p1 != 0x41) || + ((G_gpg_vstate.io_p2 != 0xA4)&&(G_gpg_vstate.io_p2 != 0xB8))) { + THROW(SW_INCORRECT_P1P2); + return SW_INCORRECT_P1P2; + } + + crt = gpg_io_fetch_u16(); + if (crt != 0x8301) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } + + ref = gpg_io_fetch_u8(); + if ((ref != 0x02) && (ref != 0x03)) { + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } + + gpg_mse_set(crt,ref); + gpg_io_discard(1); + return SW_OK; + +} \ No newline at end of file diff --git a/src/gpg_pin.c b/src/gpg_pin.c index e4fdb50..7def70f 100644 --- a/src/gpg_pin.c +++ b/src/gpg_pin.c @@ -83,6 +83,7 @@ static void gpg_pin_check_throw(gpg_pin_t *pin, int pinID, return; } THROW(sw); + return; } int gpg_pin_check(gpg_pin_t *pin, int pinID, @@ -143,10 +144,8 @@ int gpg_apdu_verify() { return SW_WRONG_DATA; } - - - //PINPAD - if (G_gpg_vstate.io_cla==0xFF) { + //PINPAD + if (G_gpg_vstate.io_cla == 0xEF) { if (gpg_pin_is_blocked(pin)) { THROW(SW_PIN_BLOCKED); return SW_PIN_BLOCKED; @@ -220,25 +219,7 @@ int gpg_apdu_change_ref_data() { gpg_pin_set_verified(pin->ref,0); - // --- RC pin --- - if (pin->ref == PIN_ID_RC) { - newlen = G_gpg_vstate.io_length; - if (newlen == 0) { - gpg_nvm_write(pin, NULL, sizeof(gpg_pin_t)); - - } - else if ((newlen > GPG_MAX_PW_LENGTH) || - (newlen < 8)) { - THROW(SW_WRONG_DATA); - return SW_WRONG_DATA; - } else { - gpg_pin_set(pin, - G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, - newlen); - } - gpg_io_discard(1); - return SW_OK; - } + // --- PW1/PW3 pin --- if (gpg_pin_is_blocked(pin)) { diff --git a/src/gpg_ram.c b/src/gpg_ram.c index eb07678..d536d5e 100644 --- a/src/gpg_ram.c +++ b/src/gpg_ram.c @@ -24,6 +24,7 @@ #ifndef GPG_DEBUG_MAIN unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; ux_state_t ux; + #else extern unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; int apdu_n; diff --git a/src/gpg_select.c b/src/gpg_select.c index d88f672..908f874 100644 --- a/src/gpg_select.c +++ b/src/gpg_select.c @@ -36,6 +36,9 @@ int gpg_apdu_select() { } gpg_io_discard(0); + if (N_gpg_pstate->histo[7] != 0x07) { + THROW(SW_STATE_TERMINATED); + } sw = SW_OK; } else { THROW(SW_FILE_NOT_FOUND); diff --git a/src/gpg_types.h b/src/gpg_types.h index 988d716..9b89fc8 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -179,6 +179,7 @@ struct gpg_v_state_s { unsigned char seed_mode; /* io state*/ + unsigned char io_cla; unsigned char io_ins; unsigned char io_p1;