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:
Cédric Mesnil 2017-09-05 23:47:16 +02:00
parent 38e143d248
commit cf6e295e47
11 changed files with 128 additions and 35 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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
};

View file

@ -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
View 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;
}

View file

@ -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)) {

View file

@ -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;

View file

@ -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);

View file

@ -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;