pin auth working
This commit is contained in:
34
fido2/ctap.c
34
fido2/ctap.c
@@ -12,11 +12,13 @@
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "device.h"
|
||||
#include "app.h"
|
||||
#include "wallet.h"
|
||||
|
||||
|
||||
#define PIN_TOKEN_SIZE 16
|
||||
static uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
||||
static uint8_t KEY_AGREEMENT_PUB[64];
|
||||
uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
||||
uint8_t KEY_AGREEMENT_PUB[64];
|
||||
static uint8_t KEY_AGREEMENT_PRIV[32];
|
||||
static uint8_t PIN_CODE_SET = 0;
|
||||
static uint8_t PIN_CODE[NEW_PIN_ENC_MAX_SIZE];
|
||||
@@ -915,10 +917,9 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, uint8_t * pinHashEnc)
|
||||
uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubkey, uint8_t * pinHashEnc)
|
||||
{
|
||||
uint8_t shared_secret[32];
|
||||
int ret;
|
||||
|
||||
crypto_ecc256_shared_secret(platform_pubkey, KEY_AGREEMENT_PRIV, shared_secret);
|
||||
|
||||
@@ -936,6 +937,9 @@ uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, u
|
||||
printf2(TAG_ERR,"Pin does not match!\n");
|
||||
printf2(TAG_ERR,"platform-pin-hash: "); dump_hex1(TAG_ERR, pinHashEnc, 16);
|
||||
printf2(TAG_ERR,"authentic-pin-hash: "); dump_hex1(TAG_ERR, PIN_CODE_HASH, 16);
|
||||
printf2(TAG_ERR,"shared-secret: "); dump_hex1(TAG_ERR, shared_secret, 32);
|
||||
printf2(TAG_ERR,"platform-pubkey: "); dump_hex1(TAG_ERR, platform_pubkey, 64);
|
||||
printf2(TAG_ERR,"device-pubkey: "); dump_hex1(TAG_ERR, KEY_AGREEMENT_PUB, 64);
|
||||
// Generate new keyAgreement pair
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
ctap_decrement_pin_attempts();
|
||||
@@ -945,12 +949,8 @@ uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, u
|
||||
ctap_reset_pin_attempts();
|
||||
crypto_aes256_reset_iv(NULL);
|
||||
|
||||
// reuse share_secret memory for encrypted pinToken
|
||||
memmove(shared_secret, PIN_TOKEN, PIN_TOKEN_SIZE);
|
||||
crypto_aes256_encrypt(shared_secret, PIN_TOKEN_SIZE);
|
||||
|
||||
ret = cbor_encode_byte_string(map, shared_secret, PIN_TOKEN_SIZE);
|
||||
check_ret(ret);
|
||||
memmove(pinTokenEnc, PIN_TOKEN, PIN_TOKEN_SIZE);
|
||||
crypto_aes256_encrypt(pinTokenEnc, PIN_TOKEN_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -959,6 +959,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
||||
{
|
||||
CTAP_clientPin CP;
|
||||
CborEncoder map;
|
||||
uint8_t pinTokenEnc[PIN_TOKEN_SIZE];
|
||||
int ret = ctap_parse_client_pin(&CP,request,length);
|
||||
|
||||
|
||||
@@ -1046,9 +1047,15 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
||||
ret = cbor_encode_int(&map, RESP_pinToken);
|
||||
check_ret(ret);
|
||||
|
||||
ret = ctap_add_pin_if_verified(&map, (uint8_t*)&CP.keyAgreement.pubkey, CP.pinHashEnc);
|
||||
/*ret = ctap_add_pin_if_verified(&map, (uint8_t*)&CP.keyAgreement.pubkey, CP.pinHashEnc);*/
|
||||
ret = ctap_add_pin_if_verified(pinTokenEnc, (uint8_t*)&CP.keyAgreement.pubkey, CP.pinHashEnc);
|
||||
check_retr(ret);
|
||||
|
||||
ret = cbor_encode_byte_string(&map, pinTokenEnc, PIN_TOKEN_SIZE);
|
||||
check_ret(ret);
|
||||
|
||||
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1214,6 +1221,11 @@ void ctap_init()
|
||||
}
|
||||
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
|
||||
#ifdef BRIDGE_TO_WALLET
|
||||
wallet_init();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
uint8_t ctap_is_pin_set()
|
||||
|
@@ -248,6 +248,8 @@ void ctap_init();
|
||||
// Resets state between different accesses of different applications
|
||||
void ctap_reset_state();
|
||||
|
||||
uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubkey, uint8_t * pinHashEnc);
|
||||
|
||||
void ctap_update_pin(uint8_t * pin, int len);
|
||||
uint8_t ctap_decrement_pin_attempts();
|
||||
int8_t ctap_leftover_pin_attempts();
|
||||
@@ -257,8 +259,9 @@ uint8_t ctap_pin_matches(uint8_t * pin, int len);
|
||||
void ctap_reset();
|
||||
int8_t ctap_device_locked();
|
||||
|
||||
|
||||
|
||||
#define PIN_TOKEN_SIZE 16
|
||||
extern uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
||||
extern uint8_t KEY_AGREEMENT_PUB[64];
|
||||
|
||||
|
||||
#endif
|
||||
|
21
fido2/u2f.c
21
fido2/u2f.c
@@ -11,6 +11,7 @@ static int16_t u2f_register(struct u2f_register_request * req);
|
||||
static int16_t u2f_version();
|
||||
static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control);
|
||||
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
|
||||
void u2f_reset_response();
|
||||
|
||||
static CTAP_RESPONSE * _u2f_resp = NULL;
|
||||
|
||||
@@ -30,23 +31,23 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
|
||||
goto end;
|
||||
}
|
||||
#ifdef BRIDGE_TO_WALLET
|
||||
struct u2f_authenticate_request * auth = (struct u2f_register_request *) req->payload;
|
||||
struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) req->payload;
|
||||
if (req->ins == U2F_AUTHENTICATE)
|
||||
{
|
||||
if (req->p1 == U2F_AUTHENTICATE_CHECK)
|
||||
{
|
||||
// if (u2f_appid_eq(&req->kh, req->app) == 0)
|
||||
// {
|
||||
// rcode = U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||
// if (u2f_appid_eq(&req->kh, req->app) == 0)
|
||||
// {
|
||||
// rcode = U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
rcode = U2F_SW_WRONG_DATA;
|
||||
// }
|
||||
// {
|
||||
rcode = U2F_SW_WRONG_DATA;
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
rcode = bridge_u2f_to_wallet(auth->chal, auth->app, auth->khl, &auth->kh);
|
||||
rcode = bridge_u2f_to_wallet(auth->chal, auth->app, auth->khl, &auth->kh);
|
||||
}
|
||||
}
|
||||
else if (req->ins == U2F_VERSION)
|
||||
@@ -140,6 +141,10 @@ int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void u2f_reset_response()
|
||||
{
|
||||
ctap_response_init(_u2f_resp);
|
||||
}
|
||||
|
||||
|
||||
static void dump_signature_der(uint8_t * sig)
|
||||
|
@@ -94,6 +94,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
|
||||
|
||||
|
||||
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
|
||||
void u2f_reset_response();
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
212
fido2/wallet.c
212
fido2/wallet.c
@@ -6,58 +6,202 @@
|
||||
*/
|
||||
#include "wallet.h"
|
||||
#include "ctap.h"
|
||||
#include "ctap_errors.h"
|
||||
#include "crypto.h"
|
||||
#include "u2f.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WalletSign = 0x10,
|
||||
WalletRegister = 0x11,
|
||||
WalletPin = 0x12,
|
||||
WalletSign = 0x10,
|
||||
WalletRegister = 0x11,
|
||||
WalletPin = 0x12,
|
||||
} WalletOperation;
|
||||
|
||||
|
||||
int16_t bridge_u2f_to_wallet(uint8_t * chal, uint8_t * appid, uint8_t klen, uint8_t * keyh)
|
||||
// return 1 if hash is valid, 0 otherwise
|
||||
int check_pinhash(uint8_t * pinAuth, uint8_t * msg, uint8_t len)
|
||||
{
|
||||
static uint8_t msg_buf[WALLET_MAX_BUFFER];
|
||||
int reqlen = klen;
|
||||
uint8_t hmac[32];
|
||||
crypto_sha256_hmac_init(PIN_TOKEN, PIN_TOKEN_SIZE, hmac);
|
||||
crypto_sha256_update(msg, 4);
|
||||
crypto_sha256_update(msg+ 4 + 16, len - 4 - 16);
|
||||
crypto_sha256_hmac_final(PIN_TOKEN, PIN_TOKEN_SIZE, hmac);
|
||||
|
||||
uint32_t count;
|
||||
uint8_t up = 1;
|
||||
uint8_t sig[72];
|
||||
printf1(TAG_WALLET, "recalc pinhash:"); dump_hex1(TAG_WALLET, hmac,32);
|
||||
|
||||
return (memcmp(pinAuth, hmac, 16) == 0);
|
||||
}
|
||||
/*int16_t wallet_sign(uint8_t alg, uint8_t * chal, uint8_t len, uint8_t * kh, uint8_t kl)*/
|
||||
/*{*/
|
||||
/*crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac);*/
|
||||
/*}*/
|
||||
|
||||
void wallet_init()
|
||||
{
|
||||
// TODO dont leave this
|
||||
printf1(TAG_WALLET,"Wallet is ready\n");
|
||||
|
||||
|
||||
ctap_update_pin("1234", 4);
|
||||
|
||||
}
|
||||
|
||||
int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * arg2)
|
||||
{
|
||||
uint8_t pinTokenEnc[PIN_TOKEN_SIZE];
|
||||
int ret;
|
||||
|
||||
switch(subcmd)
|
||||
{
|
||||
case CP_cmdGetKeyAgreement:
|
||||
printf1(TAG_WALLET,"cmdGetKeyAgreement\n");
|
||||
|
||||
u2f_response_writeback(KEY_AGREEMENT_PUB,sizeof(KEY_AGREEMENT_PUB));
|
||||
printf1(TAG_WALLET,"pubkey: "); dump_hex1(TAG_WALLET,KEY_AGREEMENT_PUB,64);
|
||||
|
||||
break;
|
||||
case CP_cmdGetRetries:
|
||||
printf1(TAG_WALLET,"cmdGetRetries\n");
|
||||
return CTAP2_ERR_UNSUPPORTED_OPTION;
|
||||
break;
|
||||
case CP_cmdSetPin:
|
||||
printf1(TAG_WALLET,"cmdSetPin\n");
|
||||
return CTAP2_ERR_UNSUPPORTED_OPTION;
|
||||
break;
|
||||
case CP_cmdChangePin:
|
||||
printf1(TAG_WALLET,"cmdChangePin\n");
|
||||
return CTAP2_ERR_UNSUPPORTED_OPTION;
|
||||
break;
|
||||
case CP_cmdGetPinToken:
|
||||
printf1(TAG_WALLET,"cmdGetPinToken\n");
|
||||
|
||||
ret = ctap_add_pin_if_verified(pinTokenEnc, arg1, pinAuth); // pubkey, pinHashEnc
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
printf1(TAG_WALLET,"pinToken: "); dump_hex1(TAG_WALLET, PIN_TOKEN, 16);
|
||||
u2f_response_writeback(pinTokenEnc, PIN_TOKEN_SIZE);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf2(TAG_ERR,"Error, invalid client pin subcommand\n");
|
||||
return CTAP2_ERR_INVALID_OPTION;
|
||||
}
|
||||
|
||||
|
||||
|
||||
wallet_request * req = (wallet_request *) msg_buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// memmove(msg_buf, chal, 32);
|
||||
memmove(msg_buf, keyh, klen);
|
||||
int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, uint8_t * keyh)
|
||||
{
|
||||
static uint8_t msg_buf[WALLET_MAX_BUFFER];
|
||||
int reqlen = klen;
|
||||
int i;
|
||||
int8_t ret = 0;
|
||||
uint32_t count;
|
||||
uint8_t up = 1;
|
||||
uint8_t sig[200];
|
||||
|
||||
count = ctap_atomic_count(0);
|
||||
uint8_t * args[5] = {NULL,NULL,NULL,NULL,NULL};
|
||||
uint8_t lens[5];
|
||||
|
||||
switch(req->operation)
|
||||
{
|
||||
case WalletSign:
|
||||
printf1(TAG_WALLET,"WalletSign\n");
|
||||
break;
|
||||
case WalletRegister:
|
||||
printf1(TAG_WALLET,"WalletRegister\n");
|
||||
break;
|
||||
case WalletPin:
|
||||
printf1(TAG_WALLET,"WalletPin\n");
|
||||
break;
|
||||
default:
|
||||
printf2(TAG_ERR,"Invalid wallet command: %x\n",req->operation);
|
||||
break;
|
||||
}
|
||||
// printf1(TAG_WALLET, "chal: "); dump_hex1(TAG_WALLET, chal,32);
|
||||
// printf1(TAG_WALLET, "appid: "); dump_hex1(TAG_WALLET, appid,32);
|
||||
// printf1(TAG_WALLET, "keyh: "); dump_hex1(TAG_WALLET, keyh,klen);
|
||||
// printf1(TAG_WALLET, "u2f2wallet: "); dump_hex1(TAG_WALLET, msg_buf,reqlen);
|
||||
|
||||
for (i = 0; i < sizeof(sig); i++)
|
||||
{
|
||||
sig[i] = i;
|
||||
}
|
||||
|
||||
wallet_request * req = (wallet_request *) msg_buf;
|
||||
uint8_t * payload = req->payload;
|
||||
|
||||
memmove(msg_buf, keyh, klen);
|
||||
|
||||
printf1(TAG_WALLET, "u2f2wallet [%d]: ",reqlen); dump_hex1(TAG_WALLET, msg_buf,reqlen);
|
||||
|
||||
count = ctap_atomic_count(0);
|
||||
u2f_response_writeback(&up,1);
|
||||
u2f_response_writeback((uint8_t *)&count,4);
|
||||
u2f_response_writeback(sig,72);
|
||||
u2f_response_writeback((uint8_t *)&ret,1);
|
||||
|
||||
return U2F_SW_NO_ERROR;
|
||||
int offset = 0;
|
||||
for (i = 0; i < MIN(5,req->numArgs); i++)
|
||||
{
|
||||
if (offset > MAX_PAYLOAD_SIZE)
|
||||
{
|
||||
ret = CTAP1_ERR_INVALID_LENGTH;
|
||||
goto cleanup;
|
||||
}
|
||||
lens[i] = *(payload + offset);
|
||||
offset++;
|
||||
args[i] = payload + offset;
|
||||
offset += lens[i];
|
||||
}
|
||||
if (offset > MAX_PAYLOAD_SIZE)
|
||||
{
|
||||
ret = CTAP1_ERR_INVALID_LENGTH;
|
||||
printf2(TAG_ERR,"Wallet operation lengths too big\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
switch(req->operation)
|
||||
{
|
||||
case WalletSign:
|
||||
printf1(TAG_WALLET,"WalletSign\n");
|
||||
printf1(TAG_WALLET,"pinAuth:"); dump_hex1(TAG_WALLET, req->pinAuth, 16);
|
||||
|
||||
if (args[0] == NULL)
|
||||
{
|
||||
ret = CTAP2_ERR_MISSING_PARAMETER;
|
||||
printf2(TAG_ERR,"Missing parameter for WalletSign\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf1(TAG_WALLET,"challenge:"); dump_hex1(TAG_WALLET, args[0], lens[0]);
|
||||
if (args[1] != NULL) printf1(TAG_WALLET,"keyid:"); dump_hex1(TAG_WALLET, args[1], lens[1]);
|
||||
|
||||
if (check_pinhash(req->pinAuth, msg_buf, reqlen))
|
||||
{
|
||||
printf1(TAG_WALLET,"pinAuth is valid\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_WALLET,"pinAuth is NOT valid\n");
|
||||
ret = CTAP2_ERR_PIN_AUTH_INVALID;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case WalletRegister:
|
||||
printf1(TAG_WALLET,"WalletRegister\n");
|
||||
break;
|
||||
case WalletPin:
|
||||
printf1(TAG_WALLET,"WalletPin\n");
|
||||
ret = wallet_pin(req->p1, req->pinAuth, args[0], args[1]);
|
||||
break;
|
||||
default:
|
||||
printf2(TAG_ERR,"Invalid wallet command: %x\n",req->operation);
|
||||
ret = CTAP1_ERR_INVALID_COMMAND;
|
||||
break;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (ret != 0)
|
||||
{
|
||||
u2f_reset_response();
|
||||
u2f_response_writeback(&up,1);
|
||||
u2f_response_writeback((uint8_t *)&count,4);
|
||||
|
||||
memset(sig,0,sizeof(sig));
|
||||
sig[0] = ret;
|
||||
u2f_response_writeback(sig,72);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*u2f_response_writeback(sig,sizeof(sig));*/
|
||||
}
|
||||
return U2F_SW_NO_ERROR;
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// op: 0x10
|
||||
// authType: 0x00 //sign?
|
||||
// reserved: 0x00 // mbedtls signature alg identifier
|
||||
// pinAuth: data[16]
|
||||
// challenge-length: 1-255
|
||||
// challenge: data[1-255]
|
||||
// keyID-length: 1-255
|
||||
@@ -53,13 +54,25 @@
|
||||
// Returns public key OR pinAuth
|
||||
|
||||
|
||||
#define MAX_CHALLENGE_SIZE 233
|
||||
#define MAX_KEYID_SIZE 232
|
||||
|
||||
#define MAX_PAYLOAD_SIZE (255 - 16 - 4)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t operation;
|
||||
uint8_t authType;
|
||||
uint8_t keyType;
|
||||
} wallet_request;
|
||||
uint8_t operation;
|
||||
uint8_t p1;
|
||||
uint8_t p2;
|
||||
uint8_t numArgs;
|
||||
uint8_t pinAuth[16];
|
||||
uint8_t payload[MAX_PAYLOAD_SIZE];
|
||||
}__attribute__((packed)) wallet_request;
|
||||
|
||||
|
||||
|
||||
int16_t bridge_u2f_to_wallet(uint8_t * chal, uint8_t * appid, uint8_t klen, uint8_t * keyh);
|
||||
|
||||
void wallet_init();
|
||||
|
||||
#endif /* WALLET_H_ */
|
||||
|
Reference in New Issue
Block a user