2019-02-12 22:18:17 +00:00
|
|
|
// 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.
|
2018-05-03 02:52:41 +00:00
|
|
|
#ifndef _CTAP_H
|
|
|
|
#define _CTAP_H
|
|
|
|
|
2018-05-25 01:26:46 +00:00
|
|
|
#include "cbor.h"
|
|
|
|
|
2018-05-03 02:52:41 +00:00
|
|
|
#define CTAP_MAKE_CREDENTIAL 0x01
|
|
|
|
#define CTAP_GET_ASSERTION 0x02
|
|
|
|
#define CTAP_CANCEL 0x03
|
|
|
|
#define CTAP_GET_INFO 0x04
|
|
|
|
#define CTAP_CLIENT_PIN 0x06
|
|
|
|
#define CTAP_RESET 0x07
|
|
|
|
#define GET_NEXT_ASSERTION 0x08
|
|
|
|
#define CTAP_VENDOR_FIRST 0x40
|
|
|
|
#define CTAP_VENDOR_LAST 0xBF
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
// AAGUID For Solo
|
|
|
|
#define CTAP_AAGUID ((uint8_t*)"\x88\x76\x63\x1b\xd4\xa0\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79")
|
2018-05-04 01:27:29 +00:00
|
|
|
|
2018-05-06 18:54:42 +00:00
|
|
|
#define MC_clientDataHash 0x01
|
|
|
|
#define MC_rp 0x02
|
|
|
|
#define MC_user 0x03
|
|
|
|
#define MC_pubKeyCredParams 0x04
|
|
|
|
#define MC_excludeList 0x05
|
|
|
|
#define MC_extensions 0x06
|
|
|
|
#define MC_options 0x07
|
|
|
|
#define MC_pinAuth 0x08
|
|
|
|
#define MC_pinProtocol 0x09
|
|
|
|
|
|
|
|
#define GA_rpId 0x01
|
|
|
|
#define GA_clientDataHash 0x02
|
|
|
|
#define GA_allowList 0x03
|
|
|
|
#define GA_extensions 0x04
|
|
|
|
#define GA_options 0x05
|
|
|
|
#define GA_pinAuth 0x06
|
|
|
|
#define GA_pinProtocol 0x07
|
|
|
|
|
|
|
|
#define CP_pinProtocol 0x01
|
|
|
|
#define CP_subCommand 0x02
|
2018-05-17 02:44:31 +00:00
|
|
|
#define CP_cmdGetRetries 0x01
|
|
|
|
#define CP_cmdGetKeyAgreement 0x02
|
|
|
|
#define CP_cmdSetPin 0x03
|
|
|
|
#define CP_cmdChangePin 0x04
|
|
|
|
#define CP_cmdGetPinToken 0x05
|
2018-05-06 18:54:42 +00:00
|
|
|
#define CP_keyAgreement 0x03
|
|
|
|
#define CP_pinAuth 0x04
|
|
|
|
#define CP_newPinEnc 0x05
|
|
|
|
#define CP_pinHashEnc 0x06
|
|
|
|
#define CP_getKeyAgreement 0x07
|
|
|
|
#define CP_getRetries 0x08
|
|
|
|
|
2018-05-13 15:36:02 +00:00
|
|
|
#define RESP_versions 0x1
|
|
|
|
#define RESP_extensions 0x2
|
|
|
|
#define RESP_aaguid 0x3
|
|
|
|
#define RESP_options 0x4
|
|
|
|
#define RESP_maxMsgSize 0x5
|
|
|
|
#define RESP_pinProtocols 0x6
|
|
|
|
|
2018-05-07 00:15:18 +00:00
|
|
|
#define RESP_fmt 0x01
|
|
|
|
#define RESP_authData 0x02
|
|
|
|
#define RESP_attStmt 0x03
|
|
|
|
|
2018-05-13 03:23:03 +00:00
|
|
|
#define RESP_credential 0x01
|
|
|
|
#define RESP_signature 0x03
|
|
|
|
#define RESP_publicKeyCredentialUserEntity 0x04
|
|
|
|
#define RESP_numberOfCredentials 0x05
|
|
|
|
|
2018-05-17 02:44:31 +00:00
|
|
|
#define RESP_keyAgreement 0x01
|
|
|
|
#define RESP_pinToken 0x02
|
|
|
|
#define RESP_retries 0x03
|
2018-05-07 00:15:18 +00:00
|
|
|
|
2018-05-06 18:54:42 +00:00
|
|
|
#define PARAM_clientDataHash (1 << 0)
|
|
|
|
#define PARAM_rp (1 << 1)
|
|
|
|
#define PARAM_user (1 << 2)
|
|
|
|
#define PARAM_pubKeyCredParams (1 << 3)
|
|
|
|
#define PARAM_excludeList (1 << 4)
|
|
|
|
#define PARAM_extensions (1 << 5)
|
|
|
|
#define PARAM_options (1 << 6)
|
|
|
|
#define PARAM_pinAuth (1 << 7)
|
|
|
|
#define PARAM_pinProtocol (1 << 8)
|
|
|
|
#define PARAM_rpId (1 << 9)
|
|
|
|
#define PARAM_allowList (1 << 10)
|
|
|
|
|
|
|
|
#define MC_requiredMask (0x0f)
|
|
|
|
|
|
|
|
|
|
|
|
#define CLIENT_DATA_HASH_SIZE 32 //sha256 hash
|
|
|
|
#define DOMAIN_NAME_MAX_SIZE 253
|
|
|
|
#define RP_NAME_LIMIT 32 // application limit, name parameter isn't needed.
|
|
|
|
#define USER_ID_MAX_SIZE 64
|
|
|
|
#define USER_NAME_LIMIT 65 // Must be minimum of 64 bytes but can be more.
|
2018-11-13 06:45:59 +00:00
|
|
|
#define DISPLAY_NAME_LIMIT 32 // Must be minimum of 64 bytes but can be more.
|
|
|
|
#define ICON_LIMIT 128 // Must be minimum of 64 bytes but can be more.
|
2018-11-11 14:04:59 +00:00
|
|
|
#define CTAP_MAX_MESSAGE_SIZE 1200
|
2018-05-06 18:54:42 +00:00
|
|
|
|
2018-11-12 16:51:43 +00:00
|
|
|
#define CREDENTIAL_RK_FLASH_PAD 2 // size of RK should be 8-byte aligned to store in flash easily.
|
2018-05-13 03:23:03 +00:00
|
|
|
#define CREDENTIAL_TAG_SIZE 16
|
2018-11-12 16:51:43 +00:00
|
|
|
#define CREDENTIAL_NONCE_SIZE (16 + CREDENTIAL_RK_FLASH_PAD)
|
2018-05-13 03:23:03 +00:00
|
|
|
#define CREDENTIAL_COUNTER_SIZE (4)
|
2018-11-12 16:51:43 +00:00
|
|
|
#define CREDENTIAL_ENC_SIZE 176 // pad to multiple of 16 bytes
|
2018-05-06 18:54:42 +00:00
|
|
|
|
|
|
|
#define PUB_KEY_CRED_PUB_KEY 0x01
|
|
|
|
#define PUB_KEY_CRED_UNKNOWN 0x3F
|
|
|
|
|
|
|
|
#define CREDENTIAL_IS_SUPPORTED 1
|
|
|
|
#define CREDENTIAL_NOT_SUPPORTED 0
|
|
|
|
|
2018-05-13 03:23:03 +00:00
|
|
|
#define ALLOW_LIST_MAX_SIZE 20
|
|
|
|
|
2018-05-22 01:57:35 +00:00
|
|
|
#define NEW_PIN_ENC_MAX_SIZE 256 // includes NULL terminator
|
2018-10-28 20:30:55 +00:00
|
|
|
#define NEW_PIN_ENC_MIN_SIZE 64
|
|
|
|
#define NEW_PIN_MAX_SIZE 64
|
|
|
|
#define NEW_PIN_MIN_SIZE 4
|
2018-05-16 03:53:41 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
#define CTAP_RESPONSE_BUFFER_SIZE 4096
|
2018-05-26 19:29:37 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
#define PIN_LOCKOUT_ATTEMPTS 8 // Number of attempts total
|
|
|
|
#define PIN_BOOT_ATTEMPTS 3 // number of attempts per boot
|
2018-07-12 01:55:20 +00:00
|
|
|
|
2018-05-13 03:23:03 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint8_t id[USER_ID_MAX_SIZE];
|
|
|
|
uint8_t id_size;
|
|
|
|
uint8_t name[USER_NAME_LIMIT];
|
2018-11-13 06:45:59 +00:00
|
|
|
uint8_t displayName[DISPLAY_NAME_LIMIT];
|
|
|
|
uint8_t icon[ICON_LIMIT];
|
2018-05-26 15:36:34 +00:00
|
|
|
}__attribute__((packed)) CTAP_userEntity;
|
2018-05-13 03:23:03 +00:00
|
|
|
|
2018-11-12 16:51:43 +00:00
|
|
|
typedef struct {
|
2018-05-26 15:36:34 +00:00
|
|
|
uint8_t tag[CREDENTIAL_TAG_SIZE];
|
|
|
|
uint8_t nonce[CREDENTIAL_NONCE_SIZE];
|
2018-11-12 16:51:43 +00:00
|
|
|
uint8_t rpIdHash[32];
|
|
|
|
uint32_t count;
|
|
|
|
}__attribute__((packed)) CredentialId;
|
|
|
|
|
|
|
|
struct Credential {
|
|
|
|
CredentialId id;
|
|
|
|
CTAP_userEntity user;
|
2018-05-13 03:23:03 +00:00
|
|
|
};
|
2018-05-06 18:54:42 +00:00
|
|
|
|
2018-11-12 16:51:43 +00:00
|
|
|
typedef struct Credential CTAP_residentKey;
|
|
|
|
|
|
|
|
|
2018-05-06 18:54:42 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint8_t aaguid[16];
|
|
|
|
uint8_t credLenH;
|
2018-05-12 03:20:10 +00:00
|
|
|
uint8_t credLenL;
|
2018-11-12 16:51:43 +00:00
|
|
|
CredentialId id;
|
2018-05-06 18:54:42 +00:00
|
|
|
} __attribute__((packed)) CTAP_attestHeader;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint8_t rpIdHash[32];
|
|
|
|
uint8_t flags;
|
|
|
|
uint32_t signCount;
|
2018-05-24 03:30:08 +00:00
|
|
|
} __attribute__((packed)) CTAP_authDataHeader;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CTAP_authDataHeader head;
|
2018-05-06 18:54:42 +00:00
|
|
|
CTAP_attestHeader attest;
|
|
|
|
} __attribute__((packed)) CTAP_authData;
|
|
|
|
|
2018-05-03 02:52:41 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2018-05-26 19:29:37 +00:00
|
|
|
uint8_t data[CTAP_RESPONSE_BUFFER_SIZE];
|
|
|
|
uint16_t data_size;
|
2018-05-03 02:52:41 +00:00
|
|
|
uint16_t length;
|
|
|
|
} CTAP_RESPONSE;
|
|
|
|
|
2018-05-13 03:23:03 +00:00
|
|
|
struct rpId
|
|
|
|
{
|
|
|
|
uint8_t id[DOMAIN_NAME_MAX_SIZE + 1]; // extra for NULL termination
|
|
|
|
size_t size;
|
|
|
|
uint8_t name[RP_NAME_LIMIT];
|
|
|
|
};
|
|
|
|
|
2018-05-06 18:54:42 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint32_t paramsParsed;
|
|
|
|
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
|
2018-05-13 03:23:03 +00:00
|
|
|
struct rpId rp;
|
|
|
|
CTAP_userEntity user;
|
2018-05-06 18:54:42 +00:00
|
|
|
|
|
|
|
uint8_t publicKeyCredentialType;
|
|
|
|
int32_t COSEAlgorithmIdentifier;
|
|
|
|
|
2018-05-25 01:26:46 +00:00
|
|
|
CborValue excludeList;
|
2018-05-25 03:13:47 +00:00
|
|
|
size_t excludeListSize;
|
2018-05-25 01:26:46 +00:00
|
|
|
|
2018-05-18 03:50:52 +00:00
|
|
|
uint8_t rk;
|
|
|
|
uint8_t uv;
|
2018-10-28 20:30:55 +00:00
|
|
|
uint8_t up;
|
2018-05-18 03:50:52 +00:00
|
|
|
|
|
|
|
uint8_t pinAuth[16];
|
|
|
|
uint8_t pinAuthPresent;
|
|
|
|
int pinProtocol;
|
2018-05-12 16:19:31 +00:00
|
|
|
|
2018-05-06 18:54:42 +00:00
|
|
|
} CTAP_makeCredential;
|
2018-05-03 02:52:41 +00:00
|
|
|
|
2018-05-13 03:23:03 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint8_t type;
|
2018-05-26 15:36:34 +00:00
|
|
|
struct Credential credential;
|
2018-05-13 03:23:03 +00:00
|
|
|
} CTAP_credentialDescriptor;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint32_t paramsParsed;
|
|
|
|
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
|
2018-10-28 20:30:55 +00:00
|
|
|
uint8_t clientDataHashPresent;
|
2018-05-13 03:23:03 +00:00
|
|
|
|
|
|
|
struct rpId rp;
|
|
|
|
|
|
|
|
int credLen;
|
2018-05-18 03:50:52 +00:00
|
|
|
|
|
|
|
uint8_t rk;
|
|
|
|
uint8_t uv;
|
2018-10-28 20:30:55 +00:00
|
|
|
uint8_t up;
|
2018-05-18 03:50:52 +00:00
|
|
|
|
|
|
|
uint8_t pinAuth[16];
|
|
|
|
uint8_t pinAuthPresent;
|
|
|
|
int pinProtocol;
|
|
|
|
|
|
|
|
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
2018-10-28 20:30:55 +00:00
|
|
|
uint8_t allowListPresent;
|
2018-05-16 03:53:41 +00:00
|
|
|
} CTAP_getAssertion;
|
2018-05-13 03:23:03 +00:00
|
|
|
|
2018-05-16 03:53:41 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int pinProtocol;
|
|
|
|
int subCommand;
|
|
|
|
struct
|
|
|
|
{
|
2018-05-18 03:11:00 +00:00
|
|
|
struct{
|
|
|
|
uint8_t x[32];
|
|
|
|
uint8_t y[32];
|
|
|
|
} pubkey;
|
|
|
|
|
2018-05-17 02:44:31 +00:00
|
|
|
int kty;
|
|
|
|
int crv;
|
2018-05-16 03:53:41 +00:00
|
|
|
} keyAgreement;
|
2018-05-18 03:11:00 +00:00
|
|
|
uint8_t keyAgreementPresent;
|
2018-05-16 03:53:41 +00:00
|
|
|
uint8_t pinAuth[16];
|
2018-05-22 01:57:35 +00:00
|
|
|
uint8_t pinAuthPresent;
|
2018-05-16 03:53:41 +00:00
|
|
|
uint8_t newPinEnc[NEW_PIN_ENC_MAX_SIZE];
|
2018-05-22 01:57:35 +00:00
|
|
|
int newPinEncSize;
|
2018-05-16 03:53:41 +00:00
|
|
|
uint8_t pinHashEnc[16];
|
2018-05-18 03:11:00 +00:00
|
|
|
uint8_t pinHashEncPresent;
|
2018-05-22 02:27:34 +00:00
|
|
|
_Bool getKeyAgreement;
|
|
|
|
_Bool getRetries;
|
2018-05-16 03:53:41 +00:00
|
|
|
} CTAP_clientPin;
|
2018-05-13 03:23:03 +00:00
|
|
|
|
|
|
|
|
2018-05-26 19:29:37 +00:00
|
|
|
void ctap_response_init(CTAP_RESPONSE * resp);
|
|
|
|
|
2018-06-02 18:44:12 +00:00
|
|
|
uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp);
|
2018-05-03 02:52:41 +00:00
|
|
|
|
2018-05-26 19:35:58 +00:00
|
|
|
// Encodes R,S signature to 2 der sequence of two integers. Sigder must be at least 72 bytes.
|
|
|
|
// @return length of der signature
|
2019-02-01 17:55:37 +00:00
|
|
|
int ctap_encode_der_sig(uint8_t const * const in_sigbuf, uint8_t * const out_sigder);
|
2018-05-26 19:29:37 +00:00
|
|
|
|
2018-05-16 03:53:41 +00:00
|
|
|
// Run ctap related power-up procedures (init pinToken, generate shared secret)
|
|
|
|
void ctap_init();
|
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
// Resets state between different accesses of different applications
|
|
|
|
void ctap_reset_state();
|
|
|
|
|
2018-07-09 02:36:16 +00:00
|
|
|
uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubkey, uint8_t * pinHashEnc);
|
2018-07-10 23:16:41 +00:00
|
|
|
uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platform_pubkey, uint8_t * pinAuth, uint8_t * pinHashEnc);
|
2018-07-09 02:36:16 +00:00
|
|
|
|
2018-05-22 01:57:35 +00:00
|
|
|
void ctap_update_pin(uint8_t * pin, int len);
|
|
|
|
uint8_t ctap_decrement_pin_attempts();
|
|
|
|
int8_t ctap_leftover_pin_attempts();
|
|
|
|
void ctap_reset_pin_attempts();
|
2018-05-22 23:58:22 +00:00
|
|
|
uint8_t ctap_is_pin_set();
|
2018-05-23 00:42:34 +00:00
|
|
|
uint8_t ctap_pin_matches(uint8_t * pin, int len);
|
2018-05-23 01:25:44 +00:00
|
|
|
void ctap_reset();
|
2018-05-23 01:36:23 +00:00
|
|
|
int8_t ctap_device_locked();
|
2018-10-28 20:30:55 +00:00
|
|
|
int8_t ctap_device_boot_locked();
|
2018-05-22 01:57:35 +00:00
|
|
|
|
2018-07-12 01:55:20 +00:00
|
|
|
// Key storage API
|
|
|
|
|
|
|
|
// Return length of key at index. 0 if not exist.
|
|
|
|
uint16_t ctap_key_len(uint8_t index);
|
|
|
|
|
|
|
|
// See error codes in storage.h
|
|
|
|
int8_t ctap_store_key(uint8_t index, uint8_t * key, uint16_t len);
|
|
|
|
int8_t ctap_load_key(uint8_t index, uint8_t * key);
|
|
|
|
uint16_t ctap_key_len(uint8_t index);
|
|
|
|
|
2018-07-09 02:36:16 +00:00
|
|
|
#define PIN_TOKEN_SIZE 16
|
|
|
|
extern uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
|
|
|
extern uint8_t KEY_AGREEMENT_PUB[64];
|
2018-05-03 02:52:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
#endif
|