merge
This commit is contained in:
143
fido2/ctap.c
143
fido2/ctap.c
@@ -1,24 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2018 SoloKeys, Inc. <https://solokeys.com/>
|
||||
*
|
||||
* This file is part of Solo.
|
||||
*
|
||||
* Solo is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Solo is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Solo. If not, see <https://www.gnu.org/licenses/>
|
||||
*
|
||||
* This code is available under licenses for commercial use.
|
||||
* Please contact SoloKeys for more information.
|
||||
*/
|
||||
// Copyright 2019 SoloKeys Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -36,6 +21,7 @@
|
||||
#include "device.h"
|
||||
#include APP_CONFIG
|
||||
#include "wallet.h"
|
||||
#include "extensions.h"
|
||||
|
||||
#include "device.h"
|
||||
|
||||
@@ -324,7 +310,7 @@ static int is_matching_rk(CTAP_residentKey * rk, CTAP_residentKey * rk2)
|
||||
}
|
||||
|
||||
|
||||
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz, int store, bool fromNFC)
|
||||
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, unsigned int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz, int store, bool fromNFC)
|
||||
{
|
||||
CborEncoder cose_key;
|
||||
int auth_data_sz, ret;
|
||||
@@ -400,8 +386,8 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
||||
memmove(&rk.id, &authData->attest.id, sizeof(CredentialId));
|
||||
memmove(&rk.user, user, sizeof(CTAP_userEntity));
|
||||
|
||||
int index = STATE.rk_stored;
|
||||
int i;
|
||||
unsigned int index = STATE.rk_stored;
|
||||
unsigned int i;
|
||||
for (i = 0; i < index; i++)
|
||||
{
|
||||
ctap_load_rk(i, &rk2);
|
||||
@@ -449,36 +435,46 @@ done_rk:
|
||||
}
|
||||
|
||||
|
||||
int ctap_encode_der_sig(uint8_t * sigbuf, uint8_t * sigder)
|
||||
/**
|
||||
*
|
||||
* @param in_sigbuf IN location to deposit signature (must be 64 bytes)
|
||||
* @param out_sigder OUT location to deposit der signature (must be 72 bytes)
|
||||
* @return length of der signature
|
||||
* // FIXME add tests for maximum and minimum length of the input and output
|
||||
*/
|
||||
int ctap_encode_der_sig(const uint8_t * const in_sigbuf, uint8_t * const out_sigder)
|
||||
{
|
||||
// Need to caress into dumb der format ..
|
||||
int i;
|
||||
int8_t lead_s = 0; // leading zeros
|
||||
int8_t lead_r = 0;
|
||||
uint8_t i;
|
||||
uint8_t lead_s = 0; // leading zeros
|
||||
uint8_t lead_r = 0;
|
||||
for (i=0; i < 32; i++)
|
||||
if (sigbuf[i] == 0) lead_r++;
|
||||
if (in_sigbuf[i] == 0) lead_r++;
|
||||
else break;
|
||||
|
||||
for (i=0; i < 32; i++)
|
||||
if (sigbuf[i+32] == 0) lead_s++;
|
||||
if (in_sigbuf[i+32] == 0) lead_s++;
|
||||
else break;
|
||||
|
||||
int8_t pad_s = ((sigbuf[32 + lead_s] & 0x80) == 0x80);
|
||||
int8_t pad_r = ((sigbuf[0 + lead_r] & 0x80) == 0x80);
|
||||
int8_t pad_s = ((in_sigbuf[32 + lead_s] & 0x80) == 0x80);
|
||||
int8_t pad_r = ((in_sigbuf[0 + lead_r] & 0x80) == 0x80);
|
||||
|
||||
sigder[0] = 0x30;
|
||||
sigder[1] = 0x44 + pad_s + pad_r - lead_s - lead_r;
|
||||
memset(out_sigder, 0, 72);
|
||||
out_sigder[0] = 0x30;
|
||||
out_sigder[1] = 0x44 + pad_s + pad_r - lead_s - lead_r;
|
||||
|
||||
sigder[2] = 0x02;
|
||||
sigder[3 + pad_r] = 0;
|
||||
sigder[3] = 0x20 + pad_r - lead_r;
|
||||
memmove(sigder + 4 + pad_r, sigbuf + lead_r, 32);
|
||||
// R ingredient
|
||||
out_sigder[2] = 0x02;
|
||||
out_sigder[3 + pad_r] = 0;
|
||||
out_sigder[3] = 0x20 + pad_r - lead_r;
|
||||
memmove(out_sigder + 4 + pad_r, in_sigbuf + lead_r, 32u - lead_r);
|
||||
|
||||
// S ingredient
|
||||
out_sigder[4 + 32 + pad_r - lead_r] = 0x02;
|
||||
out_sigder[5 + 32 + pad_r + pad_s - lead_r] = 0;
|
||||
out_sigder[5 + 32 + pad_r - lead_r] = 0x20 + pad_s - lead_s;
|
||||
memmove(out_sigder + 6 + 32 + pad_r + pad_s - lead_r, in_sigbuf + 32u + lead_s, 32u - lead_s);
|
||||
|
||||
sigder[4 + 32 + pad_r - lead_r] = 0x02;
|
||||
sigder[5 + 32 + pad_r + pad_s - lead_r] = 0;
|
||||
sigder[5 + 32 + pad_r - lead_r] = 0x20 + pad_s - lead_s;
|
||||
memmove(sigder + 6 + 32 + pad_r + pad_s - lead_r, sigbuf + 32 + lead_s, 32);
|
||||
//
|
||||
return 0x46 + pad_s + pad_r - lead_r - lead_s;
|
||||
}
|
||||
|
||||
@@ -486,8 +482,8 @@ int ctap_encode_der_sig(uint8_t * sigbuf, uint8_t * sigder)
|
||||
// @data data to hash before signature
|
||||
// @clientDataHash for signature
|
||||
// @tmp buffer for hash. (can be same as data if data >= 32 bytes)
|
||||
// @sigbuf location to deposit signature (must be 64 bytes)
|
||||
// @sigder location to deposit der signature (must be 72 bytes)
|
||||
// @sigbuf OUT location to deposit signature (must be 64 bytes)
|
||||
// @sigder OUT location to deposit der signature (must be 72 bytes)
|
||||
// @return length of der signature
|
||||
int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHash, uint8_t * hashbuf, uint8_t * sigbuf, uint8_t * sigder)
|
||||
{
|
||||
@@ -559,7 +555,8 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d
|
||||
uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length, bool fromNFC)
|
||||
{
|
||||
CTAP_makeCredential MC;
|
||||
int ret, i;
|
||||
int ret;
|
||||
unsigned int i;
|
||||
uint8_t auth_data_buf[300];
|
||||
CTAP_credentialDescriptor * excl_cred = (CTAP_credentialDescriptor *) auth_data_buf;
|
||||
uint8_t * sigbuf = auth_data_buf + 32;
|
||||
@@ -785,7 +782,18 @@ int ctap_filter_invalid_credentials(CTAP_getAssertion * GA)
|
||||
if (! ctap_authenticate_credential(&GA->rp, &GA->creds[i]))
|
||||
{
|
||||
printf1(TAG_GA, "CRED #%d is invalid\n", GA->creds[i].credential.id.count);
|
||||
GA->creds[i].credential.id.count = 0; // invalidate
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if (is_extension_request((uint8_t*)&GA->creds[i].credential.id, sizeof(CredentialId)))
|
||||
{
|
||||
printf1(TAG_EXT, "CRED #%d is extension\n", GA->creds[i].credential.id.count);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GA->creds[i].credential.id.count = 0; // invalidate
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -865,6 +873,7 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
|
||||
int ret;
|
||||
uint8_t sigbuf[64];
|
||||
uint8_t sigder[72];
|
||||
int sigder_sz;
|
||||
|
||||
if (add_user)
|
||||
{
|
||||
@@ -878,7 +887,16 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
|
||||
|
||||
crypto_ecc256_load_key((uint8_t*)&cred->credential.id, sizeof(CredentialId), NULL, 0);
|
||||
|
||||
int sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if ( extend_fido2(&cred->credential.id, sigder) )
|
||||
{
|
||||
sigder_sz = 72;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(map, RESP_signature);
|
||||
@@ -997,8 +1015,21 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length,
|
||||
ret = cbor_encoder_create_map(encoder, &map, map_size);
|
||||
check_ret(ret);
|
||||
|
||||
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0, fromNFC);
|
||||
check_retr(ret);
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if ( is_extension_request((uint8_t*)&GA.creds[validCredCount - 1].credential.id, sizeof(CredentialId)) )
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_authData);
|
||||
check_ret(ret);
|
||||
memset(auth_data_buf,0,sizeof(auth_data_buf));
|
||||
ret = cbor_encode_byte_string(&map, auth_data_buf, sizeof(auth_data_buf));
|
||||
check_ret(ret);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0, fromNFC);
|
||||
check_retr(ret);
|
||||
}
|
||||
|
||||
/*for (int j = 0; j < GA.credLen; j++)*/
|
||||
/*{*/
|
||||
@@ -1368,8 +1399,6 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool f
|
||||
CborEncoder encoder;
|
||||
uint8_t status = 0;
|
||||
uint8_t cmd = *pkt_raw;
|
||||
uint64_t t1;
|
||||
uint64_t t2;
|
||||
pkt_raw++;
|
||||
length--;
|
||||
|
||||
@@ -1402,10 +1431,9 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool f
|
||||
case CTAP_MAKE_CREDENTIAL:
|
||||
device_set_status(CTAPHID_STATUS_PROCESSING);
|
||||
printf1(TAG_CTAP,"CTAP_MAKE_CREDENTIAL\n");
|
||||
t1 = millis();
|
||||
timestamp();
|
||||
status = ctap_make_credential(&encoder, pkt_raw, length, fromNFC);
|
||||
t2 = millis();
|
||||
printf1(TAG_TIME,"make_credential time: %d ms\n", t2-t1);
|
||||
printf1(TAG_TIME,"make_credential time: %d ms\n", timestamp());
|
||||
|
||||
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
|
||||
dump_hex1(TAG_DUMP, buf, resp->length);
|
||||
@@ -1414,10 +1442,9 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool f
|
||||
case CTAP_GET_ASSERTION:
|
||||
device_set_status(CTAPHID_STATUS_PROCESSING);
|
||||
printf1(TAG_CTAP,"CTAP_GET_ASSERTION\n");
|
||||
t1 = millis();
|
||||
timestamp();
|
||||
status = ctap_get_assertion(&encoder, pkt_raw, length, fromNFC);
|
||||
t2 = millis();
|
||||
printf1(TAG_TIME,"get_assertion time: %d ms\n", t2-t1);
|
||||
printf1(TAG_TIME,"get_assertion time: %d ms\n", timestamp());
|
||||
|
||||
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
|
||||
|
||||
|
Reference in New Issue
Block a user