Adding first backend, for macOS.

In macOS, a SECP256R1 key is generated locally and stored in the keyring.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2022-10-27 19:02:03 +02:00
parent 71ecb23af6
commit e1f4e3035d
No known key found for this signature in database
GPG Key ID: C0095B7870A4CCD3
2 changed files with 57 additions and 1 deletions

View File

@ -21,6 +21,7 @@
import sys
import argparse
import platform
try:
from fido2.ctap2.config import Config
@ -44,6 +45,16 @@ except:
from enum import IntEnum
from binascii import hexlify
if (platform.system() == 'Windows'):
from secure_key import windows as skey
elif (platform.system() == 'Linux'):
from secure_key import linux as skey
elif (platform.system() == 'Darwin'):
from secure_key import macos as skey
else:
print('ERROR: platform not supported')
sys.exit(-1)
class VendorConfig(Config):
class PARAM(IntEnum):
@ -63,7 +74,7 @@ class VendorConfig(Config):
super().__init__(ctap, pin_uv_protocol, pin_uv_token)
def _get_key_device(self):
return b"\x69"*32
return skey.get_secure_key()
def _get_shared_key(self):
ret = self._call(

45
tools/secure_key/macos.py Normal file
View File

@ -0,0 +1,45 @@
import sys
import keyring
DOMAIN = "PicoKeys.com"
USERNAME = "Pico-Fido"
try:
import keyring
from keyrings.osx_keychain_keys.backend import OSXKeychainKeysBackend, OSXKeychainKeyType, OSXKeyChainKeyClassType
except:
print('ERROR: keyring module not found! Install keyring package.\nTry with `pip install keyrings.osx-keychain-keys`')
sys.exit(-1)
def get_backend(use_secure_enclave=False):
backend = OSXKeychainKeysBackend(
key_type=OSXKeychainKeyType.EC, # Key type, e.g. RSA, RC, DSA, ...
key_class_type=OSXKeyChainKeyClassType.Private, # Private key, Public key, Symmetric-key
key_size_in_bits=256,
is_permanent=True, # If set, saves the key in keychain; else, returns a transient key
use_secure_enclave=use_secure_enclave, # Saves the key in the T2 (TPM) chip, requires a code-signed interpreter
access_group=None, # Limits key management and retrieval to set group, requires a code-signed interpreter
is_extractable=True # If set, private key is extractable; else, it can't be retrieved, but only operated against
)
return backend
def generate_secure_key(use_secure_enclave=False):
backend = get_backend(use_secure_enclave)
backend.set_password(DOMAIN, USERNAME, password=None)
return backend.get_password(DOMAIN, USERNAME)
def get_d(key):
return key.private_numbers().private_value.to_bytes(32, 'big')
def get_secure_key():
key = None
try:
backend = get_backend(False)
key = backend.get_password(DOMAIN, USERNAME)[0]
except keyring.errors.KeyringError:
try:
key = generate_secure_key(False)[0] # It should be True, but secure enclave causes python segfault
except keyring.errors.PasswordSetError:
key = generate_secure_key(False)[0]
return get_d(key)