mirror of
https://github.com/LedgerHQ/openpgp-card-app
synced 2024-11-09 07:10:30 +00:00
1.1.0 fixes
Fix PIN management PINPAD CCID command was in conflict with new PIN get status APDU. Use class CLA=0xEF to differenciate both case. Fix Terminate status management Fix RC code setting Add MSE support Set MSE supported in capabilities
This commit is contained in:
parent
38e143d248
commit
cf6e295e47
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
78
src/gpg_mse.c
Normal file
78
src/gpg_mse.c
Normal file
@ -0,0 +1,78 @@
|
||||
/* Copyright 2017 Cedric Mesnil <cslashm@gmail.com>, 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;
|
||||
|
||||
}
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user