/* Copyright 2020-2021, 2023 NXP

NXP Confidential. This software is owned or controlled by NXP and may only be
used strictly in accordance with the applicable license terms. By expressly
accepting such terms or by downloading, installing, activating and/or otherwise
using the software, you are agreeing that you have read, and that you agree to
comply with and are bound by, such license terms. If you do not agree to be
bound by the applicable license terms, then you may not retain, install,
activate or otherwise use the software.*/

#pragma once

#include "windows.h"

/* usable defines */
#define FLAG_ADKP			2
#define FLAG_ODAK			16
#define SIZE_UID			8
#define SIZE_UID_EXTENDED   16
#define SIZE_ADKP_EXTENDED	32
#define SIZE_ADKP			16
#define SIZE_CHALLENGE		32
#define SIZE_WRAPPED_KEY	256

// ************************************************************
// Generate RSA-2048 key pair (wrapping keys)
// ************************************************************
ULONG _stdcall vlk_generate_wk();

// ************************************************************
// Export the RSA-2048 public key (wrapping key)
// ************************************************************
ULONG _stdcall vlk_export_wk(PBYTE WKPub, size_t *size);

// ************************************************************
// Connect to a compatible smart card and authenticate
// with the volkano applet.
// ************************************************************
ULONG _stdcall vlk_init(const char *pwd);

// ************************************************************
// Query the smart card for registered UIDs and their 
// corresponding keys.
// Returns a byte array as follows:
//   UID0 (8B) || FLAG0 (1B) || UID1 (8B) || FLAG1 (1B) || etc
// FLAG = 02 -> UID registered with ADKP
// ListSize represents the size of the structure in bytes
// n is the number of UIDs discovered
// *DEPRECATED. This function will only discover 8 byte UIDs
//     Please use vlk_discover_all_uids instead.
// ************************************************************
ULONG _stdcall vlk_discover(PBYTE UIDlist, size_t *ListSize, unsigned int *n);

// ************************************************************
// Discover the devices supported
// Returns a byte array as follows:
//   UID_SIZE (1B) || UID0 (xB) || FLAG0 (1B) || 
//   UID_SIZE (1B) || UID1 (xB) || FLAG1 (1B) || etc
// FLAG = 02 -> UID registered with ADKP
// FLAG = 16 -> UID registered with ODAK
// FLAG = 18 -> UID registered with ADKP + ODAK
// ************************************************************
ULONG _stdcall vlk_discover_all_uids(PBYTE UIDlist, size_t *ListSize, unsigned int *n);

// ************************************************************
// Register UID & ADKP
// KeyType constants to be used:
//   KeyType = 02 -> ADKP key
//   KeyType = 16 -> ODAK key
// *NOTE* pwd parameter may be omitted in this version. 
// Password provided when volkano_init was called will persist 
// for the entire lifecycle of the process 
// or until volkano_init is called again.
// ************************************************************
ULONG _stdcall vlk_register_key(PBYTE UID, size_t UIDsize, PBYTE WpedKey, size_t WpedKeySize, BYTE KeyType, const char *pwd);

// ************************************************************
// Register UID & ADKP
// KeyType constants to be used:
//   KeyType = 02 -> ADKP key
// ADKP value is provided in plain in the Key parameter
// ************************************************************
ULONG _stdcall vlk_register_key_plain(PBYTE UID, size_t UIDsize, PBYTE Key, size_t KeySize, BYTE KeyType);

// ************************************************************
// Get a response to a challenge
// *NOTE* pwd parameter may be omitted in this version. 
// Password provided when volkano_init was called will persist 
// for the entire lifecycle of the process 
// or until volkano_init is called again.
// *DEPRECATED. Please use vlk_calculate_response 
//    with scheme_id = 1 instead
// ************************************************************
ULONG _stdcall vlk_get_response(PBYTE UID, size_t UIDsize, PBYTE Chlg, size_t ChlgSize, PBYTE Resp, const char* pwd);

// ************************************************************
// Get the current version of the dll & the version of the
// volkano applet on the connected smart card, if one is
// present.
// ************************************************************
ULONG _stdcall vlk_get_version(char* version, size_t allocatedSize);

// ************************************************************
// Delete a UID record and the associated keys.
// *DEPRECATED. Please use vlk_delete_uid instead
// ************************************************************
ULONG _stdcall vlk_delete_record(PBYTE UID);

// ************************************************************
// Delete a UID + associated keys
// ************************************************************
ULONG _stdcall vlk_delete_uid(PBYTE UID, size_t UIDsize);

// ************************************************************
// Try to update the password on the smart card
// ************************************************************
ULONG _stdcall vlk_update_password(const char* newPwd);

// ************************************************************
// Check if an UID is registerd
// FoundRecord needs to be at least UIDsize bytes long
// and will be populated like this:
//   UID (8/16B) || FLAG (1B)
// FLAG = 02 -> UID registered with ADKP
// FLAG = 16 -> UID registered with ODAK
// FLAG = 18 -> UID registered with ADKP + ODAK
// ************************************************************
ULONG _stdcall vlk_discover_uid(PBYTE UID, size_t UIDsize, PBYTE FoundRecord);

// ************************************************************
// Compute the authentication tag over the wrapkey.
// ************************************************************
ULONG _stdcall vlk_get_wk_auth_tag(PBYTE AuthTag, size_t *AuthTagSize);

// ************************************************************
// Provision the second wrapkey on the smart card.
// This wrapkey will be used to export an ADKP.
// ************************************************************
ULONG _stdcall vlk_set_wk2(PBYTE WK2Pub, size_t Wk2PubSize, PBYTE AuthTag, size_t AuthTagSize);

// ************************************************************
// Export an ADKP wrapped with wrapkey_2.
// wrapkey_2 is the key provisioned with vlk_set_wk2.
// ************************************************************
ULONG _stdcall vlk_get_adkp(PBYTE UID, size_t UIDsize, PBYTE WADKP, size_t *WADKPSize);

// ************************************************************
// Get a response to a challenge by specifying a scheme id
// and a particular key.
// SchemeId constant values are:
//   1 - for HSE1 devices
//   2 - for HSE2 devices
// KeySelector constant values are:
//   FLAG_ADKP = 2;
// ************************************************************
ULONG _stdcall vlk_calculate_response(PBYTE UID, size_t UIDsize, PBYTE Chlg, size_t ChlgSize, BYTE SchemeId, BYTE KeySelector, PBYTE Resp);
