Remove legacy C implementation

This repository contains the entire history of the C source code since
the project started.

However, the code is largely translated at this point, so keeping the C
code around at this point no longer makes sense. If we need to consult
it or the history of changes, git has them.
This commit is contained in:
Tony Arcieri
2019-11-18 15:47:04 -08:00
parent 7d40a9917e
commit bf5cda9af9
9 changed files with 0 additions and 5664 deletions
-106
View File
@@ -1,106 +0,0 @@
/*
* Copyright (c) 2014-2016 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ykpiv.h"
#include <stddef.h>
#define ERR(name, desc) { name, #name, desc }
typedef struct
{
ykpiv_rc rc;
const char *name;
const char *description;
} err_t;
static const err_t *errors = {
ERR (YKPIV_OK, "Successful return"),
ERR (YKPIV_MEMORY_ERROR, "Error allocating memory"),
ERR (YKPIV_PCSC_ERROR, "Error in PCSC call"),
ERR (YKPIV_SIZE_ERROR, "Wrong buffer size"),
ERR (YKPIV_APPLET_ERROR, "No PIV application found"),
ERR (YKPIV_AUTHENTICATION_ERROR, "Error during authentication"),
ERR (YKPIV_RANDOMNESS_ERROR, "Error getting randomness"),
ERR (YKPIV_GENERIC_ERROR, "Something went wrong."),
ERR (YKPIV_KEY_ERROR, "Error in key"),
ERR (YKPIV_PARSE_ERROR, "Parse error"),
ERR (YKPIV_WRONG_PIN, "Wrong PIN code"),
ERR (YKPIV_INVALID_OBJECT, "Object invalid"),
ERR (YKPIV_ALGORITHM_ERROR, "Algorithm error"),
};
/**
* ykpiv_strerror:
* @err: error code
*
* Convert return code to human readable string explanation of the
* reason for the particular error code.
*
* This string can be used to output a diagnostic message to the user.
*
* Return value: Returns a pointer to a statically allocated string
* containing an explanation of the error code @err.
**/
const char *ykpiv_strerror(ykpiv_rc err) {
static const char *unknown = "Unknown ykpiv error";
const char *p;
if (-err < 0 || -err >= (int) (sizeof (errors) / sizeof (errors[0])))
return unknown;
p = errors[-err].description;
if (!p)
p = unknown;
return p;
}
/**
* ykpiv_strerror_name:
* @err: error code
*
* Convert return code to human readable string representing the error
* code symbol itself. For example, ykpiv_strerror_name(%YKPIV_OK)
* returns the string "YKPIV_OK".
*
* This string can be used to output a diagnostic message to the user.
*
* Return value: Returns a pointer to a statically allocated string
* containing a string version of the error code @err, or NULL if
* the error code is not known.
**/
const char *ykpiv_strerror_name(ykpiv_rc err) {
if (-err < 0 || -err >= (int) (sizeof (errors) / sizeof (errors[0])))
return NULL;
return errors[-err].name;
}
-612
View File
@@ -1,612 +0,0 @@
#ifdef _WIN32
#include <windows.h>
#ifdef _MSC_VER
#define strcasecmp _stricmp
#endif
#else
#include <ctype.h>
#include <syslog.h>
#endif
/* the _WINDOWS define really means Windows native crypto-api/CNG */
#ifdef _WINDOWS
#include <wincrypt.h>
#include <bcrypt.h>
#else
#include <openssl/des.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#endif
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <strsafe.h> /* must be included after openssl headers */
#endif
#include "internal.h"
/*
** Definitions
*/
/* crypt defines */
#ifdef _WINDOWS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
struct des_key {
HCRYPTPROV hProv;
HCRYPTKEY hKey;
ALG_ID alg;
};
static const BYTE PRIVATEKEY_EXPOF1_BLOB[] =
{
0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00,
0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6,
0x7D, 0xE8, 0xDE, 0xFB, 0x68, 0x38, 0x09, 0x92,
0xD9, 0x42, 0x7E, 0x6B, 0x89, 0x9E, 0x21, 0xD7,
0x52, 0x1C, 0x99, 0x3C, 0x17, 0x48, 0x4E, 0x3A,
0x44, 0x02, 0xF2, 0xFA, 0x74, 0x57, 0xDA, 0xE4,
0xD3, 0xC0, 0x35, 0x67, 0xFA, 0x6E, 0xDF, 0x78,
0x4C, 0x75, 0x35, 0x1C, 0xA0, 0x74, 0x49, 0xE3,
0x20, 0x13, 0x71, 0x35, 0x65, 0xDF, 0x12, 0x20,
0xF5, 0xF5, 0xF5, 0xC1, 0xED, 0x5C, 0x91, 0x36,
0x75, 0xB0, 0xA9, 0x9C, 0x04, 0xDB, 0x0C, 0x8C,
0xBF, 0x99, 0x75, 0x13, 0x7E, 0x87, 0x80, 0x4B,
0x71, 0x94, 0xB8, 0x00, 0xA0, 0x7D, 0xB7, 0x53,
0xDD, 0x20, 0x63, 0xEE, 0xF7, 0x83, 0x41, 0xFE,
0x16, 0xA7, 0x6E, 0xDF, 0x21, 0x7D, 0x76, 0xC0,
0x85, 0xD5, 0x65, 0x7F, 0x00, 0x23, 0x57, 0x45,
0x52, 0x02, 0x9D, 0xEA, 0x69, 0xAC, 0x1F, 0xFD,
0x3F, 0x8C, 0x4A, 0xD0,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0xD5, 0xAA, 0xB1,
0xA6, 0x03, 0x18, 0x92, 0x03, 0xAA, 0x31, 0x2E,
0x48, 0x4B, 0x65, 0x20, 0x99, 0xCD, 0xC6, 0x0C,
0x15, 0x0C, 0xBF, 0x3E, 0xFF, 0x78, 0x95, 0x67,
0xB1, 0x74, 0x5B, 0x60,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const DWORD PRIVATEKEY_EXPOF1_BITLEN = 512;
const ALG_ID PRIVATEKEY_EXPOF1_ALG = CALG_RSA_KEYX;
#else
struct des_key {
DES_key_schedule ks1;
DES_key_schedule ks2;
DES_key_schedule ks3;
};
#endif
/* config defines */
#ifdef _WIN32
#define _CONFIG_REGKEY "Software\\Yubico\\yubikeypiv"
#else
#define _CONFIG_FILE "/etc/yubico/yubikeypiv.conf"
#endif
#define _ENV_PREFIX "YUBIKEY_PIV_"
char *_strip_ws(char *sz);
setting_bool_t _get_bool_config(const char *sz_setting);
setting_bool_t _get_bool_env(const char *sz_setting);
/* log */
const char *szLOG_SOURCE = "YubiKey PIV Library";
/*
** Methods
*/
des_rc des_import_key(const int type, const unsigned char* keyraw, const size_t keyrawlen, des_key** key) {
des_rc rc = DES_OK;
size_t cb_expectedkey = DES_LEN_3DES;
#ifdef _WINDOWS
HCRYPTKEY hNullKey = 0;
ALG_ID alg = 0;
unsigned char* pbSessionBlob = NULL;
DWORD cbSessionBlob = 0;
DWORD cbRandom = 0;
unsigned char* pbTmp = NULL;
size_t n = 0;
switch (type) {
case DES_TYPE_3DES:
alg = CALG_3DES;
cb_expectedkey = DES_LEN_3DES;
break;
default:
rc = DES_INVALID_PARAMETER;
goto ERROR_EXIT;
}
if (!keyraw) { rc = DES_INVALID_PARAMETER; goto ERROR_EXIT; }
if (keyrawlen != cb_expectedkey) { rc = DES_INVALID_PARAMETER; goto ERROR_EXIT; }
if (!key) { rc = DES_INVALID_PARAMETER; goto ERROR_EXIT; }
if (!(*key = (des_key*)malloc(sizeof(des_key)))) { rc = DES_MEMORY_ERROR; goto ERROR_EXIT; }
memset(*key, 0, sizeof(des_key));
(*key)->alg = alg;
if (!CryptAcquireContext(&((*key)->hProv), NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { rc = DES_GENERAL_ERROR; goto ERROR_EXIT; }
// Import the exponent-of-one private key.
if (!CryptImportKey((*key)->hProv, PRIVATEKEY_EXPOF1_BLOB, sizeof(PRIVATEKEY_EXPOF1_BLOB), 0, 0, &hNullKey)) { rc = DES_GENERAL_ERROR; goto ERROR_EXIT; }
// calculate Simple blob's length
cbSessionBlob = (PRIVATEKEY_EXPOF1_BITLEN / 8) + sizeof(ALG_ID) + sizeof(BLOBHEADER);
// allocate simple blob buffer
if (!(pbSessionBlob = malloc(cbSessionBlob))) { rc = DES_MEMORY_ERROR; goto ERROR_EXIT; }
memset(pbSessionBlob, 0, cbSessionBlob);
pbTmp = pbSessionBlob;
// SIMPLEBLOB Format is documented in SDK
// Copy header to buffer
((BLOBHEADER *)pbTmp)->bType = SIMPLEBLOB;
((BLOBHEADER *)pbTmp)->bVersion = 2;
((BLOBHEADER *)pbTmp)->reserved = 0;
((BLOBHEADER *)pbTmp)->aiKeyAlg = alg;
pbTmp += sizeof(BLOBHEADER);
// Copy private key algorithm to buffer
*((DWORD *)pbTmp) = PRIVATEKEY_EXPOF1_ALG;
pbTmp += sizeof(ALG_ID);
// Place the key material in reverse order
for (n = 0; n < keyrawlen; n++) {
pbTmp[n] = keyraw[keyrawlen - n - 1];
}
// 3 is for the first reserved byte after the key material + the 2 reserved bytes at the end.
cbRandom = cbSessionBlob - (sizeof(ALG_ID) + sizeof(BLOBHEADER) + (DWORD)keyrawlen + 3);
pbTmp += (keyrawlen + 1);
// Generate random data for the rest of the buffer
// (except that last two bytes)
if (!CryptGenRandom((*key)->hProv, cbRandom, pbTmp)) { rc = DES_GENERAL_ERROR; goto ERROR_EXIT; }
for (n = 0; n < cbRandom; n++) {
if (pbTmp[n] == 0) pbTmp[n] = 1;
}
pbSessionBlob[cbSessionBlob - 2] = 2;
if (!CryptImportKey((*key)->hProv, pbSessionBlob, cbSessionBlob, hNullKey, CRYPT_EXPORTABLE, &((*key)->hKey))) { rc = DES_GENERAL_ERROR; goto ERROR_EXIT; }
#else
const_DES_cblock key_tmp;
size_t cb_keysize = 8;
switch (type) {
case DES_TYPE_3DES:
cb_expectedkey = DES_LEN_3DES;
cb_keysize = 8;
break;
default:
rc = DES_INVALID_PARAMETER;
goto ERROR_EXIT;
}
if (cb_keysize > sizeof(key_tmp)) { rc = DES_MEMORY_ERROR; goto ERROR_EXIT; }
if (!keyraw) { rc = DES_INVALID_PARAMETER; goto ERROR_EXIT; }
if (keyrawlen != cb_expectedkey) { rc = DES_INVALID_PARAMETER; goto ERROR_EXIT; }
if (!key) { rc = DES_INVALID_PARAMETER; goto ERROR_EXIT; }
if (!(*key = (des_key*)malloc(sizeof(des_key)))) { rc = DES_MEMORY_ERROR; goto ERROR_EXIT; }
memset(*key, 0, sizeof(des_key));
memcpy(key_tmp, keyraw, cb_keysize);
DES_set_key_unchecked(&key_tmp, &((*key)->ks1));
memcpy(key_tmp, keyraw + cb_keysize, cb_keysize);
DES_set_key_unchecked(&key_tmp, &((*key)->ks2));
memcpy(key_tmp, keyraw + (2 * cb_keysize), cb_keysize);
DES_set_key_unchecked(&key_tmp, &((*key)->ks3));
#endif
EXIT:
#ifdef _WINDOWS
if (pbSessionBlob) {
yc_memzero(pbSessionBlob, cbSessionBlob);
free(pbSessionBlob);
pbSessionBlob = NULL;
}
if (hNullKey) {
CryptDestroyKey(hNullKey);
hNullKey = 0;
}
#endif
return rc;
ERROR_EXIT:
if (key) {
des_destroy_key(*key);
*key = NULL;
}
goto EXIT;
}
des_rc des_destroy_key(des_key* key) {
if (key) {
#ifdef _WINDOWS
if (key->hKey) {
CryptDestroyKey(key->hKey);
key->hKey = 0;
}
if (key->hProv) {
CryptReleaseContext(key->hProv, 0);
key->hProv = 0;
}
#endif
free(key);
}
return DES_OK;
}
des_rc des_encrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen) {
des_rc rc = DES_OK;
#ifdef _WINDOWS
unsigned char buf[8] = { 0 };
size_t buflen = sizeof(buf);
#endif
if (!key || !outlen || (*outlen < inlen) || !in || !out) { rc = DES_INVALID_PARAMETER; goto EXIT; }
#ifdef _WINDOWS
if (!key->hKey) { rc = DES_INVALID_PARAMETER; goto EXIT; }
memcpy(out, in, inlen);
*outlen = inlen;
if (!CryptEncrypt(key->hKey, 0, FALSE, 0, out, (DWORD*)&inlen, (DWORD)*outlen)) { fwprintf(stderr, L"GetLastError = %x\n", GetLastError()); rc = DES_GENERAL_ERROR; goto EXIT; }
// reset key usage by encrypting a fake padded block
CryptEncrypt(key->hKey, 0, TRUE, 0, buf, (DWORD*)&buflen, (DWORD)buflen);
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
/* openssl returns void */
DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 1);
#pragma GCC diagnostic pop
#endif
EXIT:
return rc;
}
des_rc des_decrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen) {
des_rc rc = DES_OK;
#ifdef _WINDOWS
unsigned char buf[8] = { 0 };
size_t buflen = sizeof(buf);
#endif
if (!key || !outlen || (*outlen < inlen) || !in || !out) { rc = DES_INVALID_PARAMETER; goto EXIT; }
#ifdef _WINDOWS
if (!key->hKey) { rc = DES_INVALID_PARAMETER; goto EXIT; }
memcpy(out, in, inlen);
*outlen = inlen;
if (!CryptDecrypt(key->hKey, 0, FALSE, 0, out, (DWORD*)outlen)) { fwprintf(stderr, L"GetLastError = %x\n", GetLastError()); rc = DES_GENERAL_ERROR; goto EXIT; }
// reset key usage by decrypting a fake padded block
CryptDecrypt(key->hKey, 0, TRUE, 0, buf, (DWORD*)&buflen);
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
/* openssl returns void */
DES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 0);
#pragma GCC diagnostic pop
#endif
EXIT:
return rc;
}
bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key) {
#ifdef _WINDOWS
bool rv = false;
/* defined weak keys, borrowed from openssl to be consistent across platforms */
static const unsigned char weak_keys[][DES_LEN_DES] = {
/* weak keys */
{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
{0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
{0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
{0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},
/* semi-weak keys */
{0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE},
{0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
{0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
{0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
{0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
{0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
{0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
{0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
{0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
{0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
{0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
{0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1} };
unsigned char tmp[DES_LEN_3DES] = { 0 };
int i = 0;
unsigned char c = 0x00;
if (sizeof(tmp) != cb_key) return true;
/* set odd parity of key */
for (i = 0; i < sizeof(tmp); i++) {
/* count number of set bits in byte, excluding the low-order bit - SWAR method */
c = key[i] & 0xFE;
c = (c & 0x55) + ((c >> 1) & 0x55);
c = (c & 0x33) + ((c >> 2) & 0x33);
c = (c & 0x0F) + ((c >> 4) & 0x0F);
/* if count is even, set low key bit to 1, otherwise 0 */
tmp[i] = (key[i] & 0xFE) | ((c & 0x01) ? 0x00 : 0x01);
}
/* check odd parity key against table by DES key block*/
for (i = 0; i < sizeof(weak_keys) / sizeof(weak_keys[0]); i++) {
if ((0 == memcmp(weak_keys[i], tmp, DES_LEN_DES)) ||
(0 == memcmp(weak_keys[i], tmp + DES_LEN_DES, DES_LEN_DES)) ||
(0 == memcmp(weak_keys[i], tmp + 2*DES_LEN_DES, DES_LEN_DES))) {
rv = true;
break;
}
}
yc_memzero(tmp, DES_LEN_3DES);
return rv;
#else
(void)cb_key; /* unused */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
return DES_is_weak_key((const_DES_cblock *)key);
#pragma GCC diagnostic pop
#endif
}
prng_rc _ykpiv_prng_generate(unsigned char *buffer, const size_t cb_req) {
prng_rc rc = PRNG_OK;
#ifdef _WINDOWS
HCRYPTPROV hProv = 0;
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
if (!CryptGenRandom(hProv, (DWORD)cb_req, buffer)) {
rc = PRNG_GENERAL_ERROR;
}
CryptReleaseContext(hProv, 0);
}
else {
rc = PRNG_GENERAL_ERROR;
}
#else
if (-1 == RAND_bytes(buffer, cb_req)) {
rc = PRNG_GENERAL_ERROR;
}
#endif
return rc;
}
pkcs5_rc pkcs5_pbkdf2_sha1(const uint8_t* password, const size_t cb_password, const uint8_t* salt, const size_t cb_salt, uint64_t iterations, const uint8_t* key, const size_t cb_key) {
pkcs5_rc rc = PKCS5_OK;
#ifdef _WINDOWS
BCRYPT_ALG_HANDLE hAlg = 0;
/* mingw64 defines the BCryptDeriveKeyPBKDF2 function, but its dll link library doesn't include the export.
**
** In case this is needed, we'll need to dynamically load the function:
**
** typedef NTSTATUS WINAPI (*PFN_BCryptDeriveKeyPBKDF2) (BCRYPT_ALG_HANDLE hPrf, PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, ULONGLONG cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey, ULONG dwFlags);
** HMODULE hBCrypt = LoadLibrary("bcrypt.dll");
** PFN_BCryptDeriveKeyPBKDF2 pbkdf2 = GetProcAddress(hBCrypt, "BCryptDeriveKeyPBKDF2");
*/
if (STATUS_SUCCESS == BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG)) {
/* suppress const qualifier warning b/c BCrypt doesn't take const input buffers */
#pragma warning(suppress: 4090)
if (STATUS_SUCCESS != BCryptDeriveKeyPBKDF2(hAlg, (PUCHAR)password, (ULONG)cb_password, (PUCHAR)salt, (ULONG)cb_salt, iterations, key, (ULONG)cb_key, 0)) {
rc = PKCS5_GENERAL_ERROR;
}
BCryptCloseAlgorithmProvider(hAlg, 0);
}
else {
rc = PKCS5_GENERAL_ERROR;
}
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
/* for some reason openssl always returns 1 for PBKDF2 */
PKCS5_PBKDF2_HMAC_SHA1((const char*)password, cb_password, salt, cb_salt, iterations, cb_key, (unsigned char*)key);
#pragma GCC diagnostic pop
#endif
return rc;
}
/* settings */
char *_strip_ws(char *sz) {
char *psz_head = sz;
char *psz_tail = sz + strlen(sz) - 1;
/* strip leading whitespace */
while (isspace(*psz_head)) {
psz_head++;
}
/* strip trailing whitespace */
while ((psz_tail >= psz_head) && isspace(*psz_tail)) {
*psz_tail-- = '\0';
}
return psz_head;
}
setting_bool_t _get_bool_config(const char *sz_setting) {
setting_bool_t setting = { false, SETTING_SOURCE_DEFAULT };
#ifdef _WIN32
HKEY hKey = 0;
DWORD dwValue = 0;
DWORD dwType = 0;
DWORD cbValue = sizeof(dwValue);
/* MINGW doesn't define RRF_SUBKEY_WOW6464KEY for RegGetValue, so read the traditional way */
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, _CONFIG_REGKEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey) == 0) {
if (RegQueryValueExA(hKey, sz_setting, NULL, &dwType, (LPBYTE)&dwValue, &cbValue) == 0) {
setting.value = ((dwType == REG_DWORD) && (dwValue == 1));
setting.source = SETTING_SOURCE_ADMIN;
}
RegCloseKey(hKey);
hKey = 0;
}
#else
/* read from config file*/
char sz_line[256];
char *psz_name = 0;
char *psz_value = 0;
char sz_name[256]; /* XXX REMEMBER TO ZERO */
char sz_value[256]; /* XXX REMEMBER TO ZERO */
FILE *pf = 0;
if ((pf = fopen(_CONFIG_FILE, "r"))) {
while (!feof(pf)) {
if (fgets(sz_line, sizeof(sz_line), pf)) {
if (sz_line[0] == '#') continue;
if (sz_line[0] == '\r') continue;
if (sz_line[0] == '\n') continue;
if (sscanf(sz_line, "%255[^=]=%255s", sz_name, sz_value) == 2) {
/* strip leading/trailing whitespace */
psz_name = _strip_ws(sz_name);
if (!strcasecmp(psz_name, sz_setting)) {
psz_value = _strip_ws(sz_value);
setting.source = SETTING_SOURCE_ADMIN;
setting.value = (!strcmp(psz_value, "1") || !strcasecmp(psz_value, "true"));
break;
}
}
}
}
fclose(pf);
}
#endif
return setting;
}
setting_bool_t _get_bool_env(const char *sz_setting) {
setting_bool_t setting = { false, SETTING_SOURCE_DEFAULT };
char *psz_value = NULL;
char sz_name[256]; /* XXX REMEMBER TO ZERO */
snprintf(sz_name, sizeof(sz_name) - 1, "%s%s", _ENV_PREFIX, sz_setting);
/* MINGW does not implement getenv_s, only _wgetenv_s */
#ifdef _MSC_VER
size_t cb_value = 0;
char sz_value[100] = { 0 };
if ((getenv_s(&cb_value, sz_value, sizeof(sz_value) - 1, sz_name) == 0) && (cb_value > 0)) {
psz_value = sz_value;
}
#else
psz_value = getenv(sz_name);
#endif
if (psz_value) {
setting.source = SETTING_SOURCE_USER;
setting.value = (!strcmp(psz_value, "1") || !strcasecmp(psz_value, "true"));
}
return setting;
}
setting_bool_t setting_get_bool(const char *sz_setting, bool def) {
setting_bool_t setting = { def, SETTING_SOURCE_DEFAULT };
setting = _get_bool_config(sz_setting);
if (setting.source == SETTING_SOURCE_DEFAULT) {
setting = _get_bool_env(sz_setting);
}
if (setting.source == SETTING_SOURCE_DEFAULT) {
setting.value = def;
}
return setting;
}
-258
View File
@@ -1,258 +0,0 @@
/*
* Copyright (c) 2014-2016 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef YKPIV_INTERNAL_H
#define YKPIV_INTERNAL_H
#include "ykpiv.h"
#include <stdbool.h>
#if BACKEND_PCSC
#if defined HAVE_PCSC_WINSCARD_H
# include <PCSC/wintypes.h>
# include <PCSC/winscard.h>
#else
# include <winscard.h>
#endif
#endif
// Typedef DWORD (defined by pcsc lib) to pcsc_word to make it clear that this
// is not the Windows meaning of DWORD, but the PCSC library's meaning. This
// differs: Windows defines a DWORD as 32-bits, but pcsclite defines it as
// 'unsigned long' on x86_64 Linux, which is often 64-bits.
typedef DWORD pcsc_word;
#ifdef __cplusplus
extern "C"
{
#endif
#define DES_TYPE_3DES 1
#define DES_LEN_DES 8
#define DES_LEN_3DES DES_LEN_DES*3
#define READER_LEN 32
#define MAX_READERS 16
#define CB_MGM_KEY DES_LEN_3DES
// the object size is restricted to the firmware's message buffer size, which
// always contains 0x5C + 1 byte len + 3 byte id + 0x53 + 3 byte len = 9 bytes,
// so while the message buffer == CB_BUF_MAX, the maximum object we can store
// is CB_BUF_MAX - 9
#define CB_OBJ_MAX_NEO (CB_BUF_MAX_NEO - 9)
#define CB_OBJ_MAX_YK4 (CB_BUF_MAX_YK4 - 9)
#define CB_OBJ_MAX 3063
#define CB_BUF_MAX_NEO 2048
#define CB_BUF_MAX_YK4 3072
#define CB_BUF_MAX CB_BUF_MAX_YK4
#define CB_ATR_MAX 33
#define CHREF_ACT_CHANGE_PIN 0
#define CHREF_ACT_UNBLOCK_PIN 1
#define CHREF_ACT_CHANGE_PUK 2
#define TAG_CERT 0x70
#define TAG_CERT_COMPRESS 0x71
#define TAG_CERT_LRC 0xFE
#define TAG_ADMIN 0x80
#define TAG_ADMIN_FLAGS_1 0x81
#define TAG_ADMIN_SALT 0x82
#define TAG_ADMIN_TIMESTAMP 0x83
#define TAG_PROTECTED 0x88
#define TAG_PROTECTED_FLAGS_1 0x81
#define TAG_PROTECTED_MGM 0x89
#define TAG_MSCMAP 0x81
#define TAG_MSROOTS_END 0x82
#define TAG_MSROOTS_MID 0x83
#define TAG_RSA_MODULUS 0x81
#define TAG_RSA_EXP 0x82
#define TAG_ECC_POINT 0x86
#define CB_ECC_POINTP256 65
#define CB_ECC_POINTP384 97
#define YKPIV_OBJ_ADMIN_DATA 0x5fff00
#define YKPIV_OBJ_ATTESTATION 0x5fff01
#define YKPIV_OBJ_MSCMAP 0x5fff10
#define YKPIV_OBJ_MSROOTS1 0x5fff11
#define YKPIV_OBJ_MSROOTS2 0x5fff12
#define YKPIV_OBJ_MSROOTS3 0x5fff13
#define YKPIV_OBJ_MSROOTS4 0x5fff14
#define YKPIV_OBJ_MSROOTS5 0x5fff15
#define ADMIN_FLAGS_1_PUK_BLOCKED 0x01
#define ADMIN_FLAGS_1_PROTECTED_MGM 0x02
#define CB_ADMIN_SALT 16
#define CB_ADMIN_TIMESTAMP 4
#define ITER_MGM_PBKDF2 10000
#define PROTECTED_FLAGS_1_PUK_NOBLOCK 0x01
#define CB_OBJ_TAG_MIN 2 // 1 byte tag + 1 byte len
#define CB_OBJ_TAG_MAX (CB_OBJ_TAG_MIN + 2) // 1 byte tag + 3 bytes len
#define CB_PIN_MAX 8
#define member_size(type, member) sizeof(((type*)0)->member)
typedef enum {
DES_OK = 0,
DES_INVALID_PARAMETER = -1,
DES_BUFFER_TOO_SMALL = -2,
DES_MEMORY_ERROR = -3,
DES_GENERAL_ERROR = -4
} des_rc;
typedef enum {
PKCS5_OK = 0,
PKCS5_GENERAL_ERROR = -1
} pkcs5_rc;
typedef enum {
PRNG_OK = 0,
PRNG_GENERAL_ERROR = -1
} prng_rc;
typedef struct _ykpiv_version_t {
uint8_t major;
uint8_t minor;
uint8_t patch;
} ykpiv_version_t;
struct ykpiv_state {
SCARDCONTEXT context;
SCARDHANDLE card;
int verbose;
char *pin;
ykpiv_allocator allocator;
bool isNEO;
ykpiv_version_t ver;
uint32_t serial;
};
union u_APDU {
struct {
unsigned char cla;
unsigned char ins;
unsigned char p1;
unsigned char p2;
unsigned char lc;
unsigned char data[0xff];
} st;
unsigned char raw[0xff + 5];
};
typedef union u_APDU APDU;
typedef struct des_key des_key;
des_rc des_import_key(const int type, const unsigned char* keyraw, const size_t keyrawlen, des_key** key);
des_rc des_destroy_key(des_key* key);
des_rc des_encrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen);
des_rc des_decrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen);
pkcs5_rc pkcs5_pbkdf2_sha1(const uint8_t* password, const size_t cb_password, const uint8_t* salt, const size_t cb_salt, uint64_t iterations, const uint8_t* key, const size_t cb_key);
bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key);
prng_rc _ykpiv_prng_generate(unsigned char *buffer, const size_t cb_req);
ykpiv_rc _ykpiv_begin_transaction(ykpiv_state *state);
ykpiv_rc _ykpiv_end_transaction(ykpiv_state *state);
ykpiv_rc _ykpiv_ensure_application_selected(ykpiv_state *state);
ykpiv_rc _ykpiv_select_application(ykpiv_state *state);
unsigned int _ykpiv_set_length(unsigned char *buffer, size_t length);
unsigned int _ykpiv_get_length(const unsigned char *buffer, size_t *len);
bool _ykpiv_has_valid_length(const unsigned char* buffer, size_t len);
void* _ykpiv_alloc(ykpiv_state *state, size_t size);
void* _ykpiv_realloc(ykpiv_state *state, void *address, size_t size);
void _ykpiv_free(ykpiv_state *state, void *data);
ykpiv_rc _ykpiv_save_object(ykpiv_state *state, int object_id, unsigned char *indata, size_t len);
ykpiv_rc _ykpiv_fetch_object(ykpiv_state *state, int object_id, unsigned char *data, unsigned long *len);
ykpiv_rc _send_data(ykpiv_state *state, APDU *apdu, unsigned char *data, uint32_t *recv_len, int *sw);
ykpiv_rc _ykpiv_transfer_data(
ykpiv_state *state,
const unsigned char *templ,
const unsigned char *in_data,
long in_len,
unsigned char *out_data,
unsigned long *out_len,
int *sw);
/* authentication functions not ready for public api */
ykpiv_rc ykpiv_auth_getchallenge(ykpiv_state *state, uint8_t *challenge, const size_t challenge_len);
ykpiv_rc ykpiv_auth_verifyresponse(ykpiv_state *state, uint8_t *response, const size_t response_len);
ykpiv_rc ykpiv_auth_deauthenticate(ykpiv_state *state);
typedef enum _setting_source_t {
SETTING_SOURCE_USER,
SETTING_SOURCE_ADMIN,
SETTING_SOURCE_DEFAULT
} setting_source_t;
typedef struct _setting_bool_t {
bool value;
setting_source_t source;
} setting_bool_t;
setting_bool_t setting_get_bool(const char *sz_setting, bool f_default);
typedef enum _yc_log_level_t {
YC_LOG_LEVEL_ERROR,
YC_LOG_LEVEL_WARN,
YC_LOG_LEVEL_INFO,
YC_LOG_LEVEL_VERBOSE,
YC_LOG_LEVEL_DEBUG
} yc_log_level_t;
#ifdef _WIN32
#include <windows.h>
#define yc_memzero SecureZeroMemory
#elif defined(BSD)
#include <strings.h>
#define yc_memzero explicit_bzero
#elif defined(__linux__)
#include <openssl/crypto.h>
#define yc_memzero OPENSSL_cleanse
#else
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#define yc_memzero(_p, _n) (void)memset_s(_p, (rsize_t)_n, 0, (rsize_t)_n)
#endif
#ifdef __cplusplus
}
#endif
#endif
-1681
View File
File diff suppressed because it is too large Load Diff
-143
View File
@@ -1,143 +0,0 @@
/*
* Copyright (c) 2014-2016 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ykpiv-version.h"
#include <stddef.h>
#include <string.h>
/* From https://article.gmane.org/gmane.os.freebsd.devel.hackers/23606 */
static int my_strverscmp (const char *s1, const char *s2)
{
static const char *digits = "0123456789";
size_t p1, p2;
p1 = strcspn (s1, digits);
p2 = strcspn (s2, digits);
while (p1 == p2 && s1[p1] != '\0' && s2[p2] != '\0') {
int ret, lz1, lz2;
/* Different prefix */
if ((ret = strncmp (s1, s2, p1)) != 0)
return ret;
s1 += p1;
s2 += p2;
lz1 = lz2 = 0;
if (*s1 == '0')
lz1 = 1;
if (*s2 == '0')
lz2 = 1;
if (lz1 > lz2)
return -1;
else if (lz1 < lz2)
return 1;
else if (lz1 == 1) {
/*
* If the common prefix for s1 and s2 consists only of zeros, then the
* "longer" number has to compare less. Otherwise the comparison needs
* to be numerical (just fallthrough). See
* https://refspecs.linuxfoundation.org/LSB_2.0.1/LSB-generic/
* https://refspecs.linuxfoundation.org/LSB_2.0.1/LSB-generic/LSB-generic/baselib-strverscmp.html
*/
while (*s1 == '0' && *s2 == '0') {
++s1;
++s2;
}
p1 = strspn (s1, digits);
p2 = strspn (s2, digits);
/* Catch empty strings */
if (p1 == 0 && p2 > 0)
return 1;
else if (p2 == 0 && p1 > 0)
return -1;
/* Prefixes are not same */
if (*s1 != *s2 && *s1 != '0' && *s2 != '0') {
if (p1 < p2)
return 1;
else if (p1 > p2)
return -1;
} else {
if (p1 < p2)
ret = strncmp (s1, s2, p1);
else if (p1 > p2)
ret = strncmp (s1, s2, p2);
if (ret != 0)
return ret;
}
}
p1 = strspn (s1, digits);
p2 = strspn (s2, digits);
if (p1 < p2)
return -1;
else if (p1 > p2)
return 1;
else if ((ret = strncmp (s1, s2, p1)) != 0)
return ret;
/* Numbers are equal or not present, try with next ones. */
s1 += p1;
s2 += p2;
p1 = strcspn (s1, digits);
p2 = strcspn (s2, digits);
}
return strcmp (s1, s2);
}
/**
* ykpiv_check_version:
* @req_version: Required version number, or NULL.
*
* Check that the version of the library is at minimum the requested
* one and return the version string; return NULL if the condition is
* not satisfied. If a NULL is passed to this function, no check is
* done, but the version string is simply returned.
*
* See %YKPIV_VERSION_STRING for a suitable @req_version string.
*
* Return value: Version string of run-time library, or NULL if the
* run-time library does not meet the required version number.
*/
const char * ykpiv_check_version (const char *req_version)
{
if (!req_version
|| my_strverscmp (req_version, YKPIV_VERSION_STRING) <= 0)
return YKPIV_VERSION_STRING;
return NULL;
}
-92
View File
@@ -1,92 +0,0 @@
/*
* Copyright (c) 2014-2016 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef YKPIV_VERSION_H
#define YKPIV_VERSION_H
#ifdef __cplusplus
extern "C"
{
#endif
/**
* YKPIV_VERSION_STRING
*
* Pre-processor symbol with a string that describe the header file
* version number. Used together with ykneomgr_check_version() to verify
* header file and run-time library consistency.
*/
#define YKPIV_VERSION_STRING "@VERSION@"
/**
* YKPIV_VERSION_NUMBER
*
* Pre-processor symbol with a hexadecimal value describing the header
* file version number. For example, when the header version is 1.2.3
* this symbol will have the value 0x01020300. The last two digits
* are only used between public releases, and will otherwise be 00.
*/
#define YKPIV_VERSION_NUMBER @YKPIV_VERSION_NUMBER@
/**
* YKPIV_VERSION_MAJOR
*
* Pre-processor symbol with a decimal value that describe the major
* level of the header file version number. For example, when the
* header version is 1.2.3 this symbol will be 1.
*/
#define YKPIV_VERSION_MAJOR @YKPIV_VERSION_MAJOR@
/**
* YKPIV_VERSION_MINOR
*
* Pre-processor symbol with a decimal value that describe the minor
* level of the header file version number. For example, when the
* header version is 1.2.3 this symbol will be 2.
*/
#define YKPIV_VERSION_MINOR @YKPIV_VERSION_MINOR@
/**
* YKPIV_VERSION_PATCH
*
* Pre-processor symbol with a decimal value that describe the patch
* level of the header file version number. For example, when the
* header version is 1.2.3 this symbol will be 3.
*/
#define YKPIV_VERSION_PATCH @YKPIV_VERSION_PATCH@
const char *ykpiv_check_version (const char *req_version);
#ifdef __cplusplus
}
#endif
#endif
-92
View File
@@ -1,92 +0,0 @@
/*
* Copyright (c) 2014-2016 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef YKPIV_VERSION_H
#define YKPIV_VERSION_H
#ifdef __cplusplus
extern "C"
{
#endif
/**
* YKPIV_VERSION_STRING
*
* Pre-processor symbol with a string that describe the header file
* version number. Used together with ykneomgr_check_version() to verify
* header file and run-time library consistency.
*/
#define YKPIV_VERSION_STRING "@VERSION@"
/**
* YKPIV_VERSION_NUMBER
*
* Pre-processor symbol with a hexadecimal value describing the header
* file version number. For example, when the header version is 1.2.3
* this symbol will have the value 0x01020300. The last two digits
* are only used between public releases, and will otherwise be 00.
*/
#define YKPIV_VERSION_NUMBER @YKPIV_VERSION_NUMBER@
/**
* YKPIV_VERSION_MAJOR
*
* Pre-processor symbol with a decimal value that describe the major
* level of the header file version number. For example, when the
* header version is 1.2.3 this symbol will be 1.
*/
#define YKPIV_VERSION_MAJOR @YKPIV_VERSION_MAJOR@
/**
* YKPIV_VERSION_MINOR
*
* Pre-processor symbol with a decimal value that describe the minor
* level of the header file version number. For example, when the
* header version is 1.2.3 this symbol will be 2.
*/
#define YKPIV_VERSION_MINOR @YKPIV_VERSION_MINOR@
/**
* YKPIV_VERSION_PATCH
*
* Pre-processor symbol with a decimal value that describe the patch
* level of the header file version number. For example, when the
* header version is 1.2.3 this symbol will be 3.
*/
#define YKPIV_VERSION_PATCH @YKPIV_VERSION_PATCH@
const char *ykpiv_check_version (const char *req_version);
#ifdef __cplusplus
}
#endif
#endif
-1978
View File
File diff suppressed because it is too large Load Diff
-702
View File
@@ -1,702 +0,0 @@
/*
* Copyright (c) 2014-2016 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @mainpage
*
* See ykpiv.h
*
* @file ykpiv.h
* libykpiv API
*/
#ifndef YKPIV_H
#define YKPIV_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <ykpiv-version.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct ykpiv_state ykpiv_state;
typedef enum {
YKPIV_OK = 0,
YKPIV_MEMORY_ERROR = -1,
YKPIV_PCSC_ERROR = -2,
YKPIV_SIZE_ERROR = -3,
YKPIV_APPLET_ERROR = -4,
YKPIV_AUTHENTICATION_ERROR = -5,
YKPIV_RANDOMNESS_ERROR = -6,
YKPIV_GENERIC_ERROR = -7,
YKPIV_KEY_ERROR = -8,
YKPIV_PARSE_ERROR = -9,
YKPIV_WRONG_PIN = -10,
YKPIV_INVALID_OBJECT = -11,
YKPIV_ALGORITHM_ERROR = -12,
YKPIV_PIN_LOCKED = -13,
YKPIV_ARGUMENT_ERROR = -14, //i.e. invalid input argument
YKPIV_RANGE_ERROR = -15, //i.e. value range error
YKPIV_NOT_SUPPORTED = -16
} ykpiv_rc;
typedef void* (*ykpiv_pfn_alloc)(void* alloc_data, size_t size);
typedef void* (*ykpiv_pfn_realloc)(void* alloc_data, void* address, size_t size);
typedef void (*ykpiv_pfn_free)(void* alloc_data, void* address);
typedef struct ykpiv_allocator {
ykpiv_pfn_alloc pfn_alloc;
ykpiv_pfn_realloc pfn_realloc;
ykpiv_pfn_free pfn_free;
void * alloc_data;
} ykpiv_allocator;
const char *ykpiv_strerror(ykpiv_rc err);
const char *ykpiv_strerror_name(ykpiv_rc err);
ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose);
ykpiv_rc ykpiv_init_with_allocator(ykpiv_state **state, int verbose, const ykpiv_allocator *allocator);
ykpiv_rc ykpiv_done(ykpiv_state *state);
ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted);
ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len);
ykpiv_rc ykpiv_disconnect(ykpiv_state *state);
ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
const unsigned char *in_data, long in_len,
unsigned char *out_data, unsigned long *out_len, int *sw);
ykpiv_rc ykpiv_authenticate(ykpiv_state *state, const unsigned char *key);
ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key);
ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len,
unsigned char *hex_out, size_t *out_len);
ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in,
size_t in_len, unsigned char *sign_out, size_t *out_len,
unsigned char algorithm, unsigned char key);
ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *enc_in,
size_t in_len, unsigned char *enc_out, size_t *out_len,
unsigned char algorithm, unsigned char key);
ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len);
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries);
ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len,
const char * new_pin, size_t new_pin_len,
int *tries);
ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len,
const char * new_puk, size_t new_puk_len,
int *tries);
ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len,
const char * new_pin, size_t new_pin_len,
int *tries);
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
unsigned char *data, unsigned long *len);
ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key,
const unsigned char touch);
ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
unsigned char *indata, size_t len);
ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, unsigned char algorithm,
const unsigned char *p, size_t p_len,
const unsigned char *q, size_t q_len,
const unsigned char *dp, size_t dp_len,
const unsigned char *dq, size_t dq_len,
const unsigned char *qinv, size_t qinv_len,
const unsigned char *ec_data, unsigned char ec_data_len,
const unsigned char pin_policy, const unsigned char touch_policy);
ykpiv_rc ykpiv_attest(ykpiv_state *state, const unsigned char key, unsigned char *data, size_t *data_len);
/**
* Return the number of PIN attempts remaining before PIN is locked.
*
* **NOTE:** If PIN is already verified, calling ykpiv_get_pin_retries() will unverify the PIN.
*
* @param state State handle from ykpiv_init()
* @param tries [out] Number of attempts remaining
*
* @return Error code
*/
ykpiv_rc ykpiv_get_pin_retries(ykpiv_state *state, int *tries);
/**
* Set number of attempts before locking for PIN and PUK codes.
*
* **NOTE:** If either \p pin_tries or \p puk_tries is 0, ykpiv_set_pin_retries() immediately returns YKPIV_OK.
*
* @param state State handle from ykpiv_init()
* @param pin_tries Number of attempts to permit for PIN code
* @param puk_tries Number of attempts to permit for PUK code
*
* @return Error code
*/
ykpiv_rc ykpiv_set_pin_retries(ykpiv_state *state, int pin_tries, int puk_tries);
/**
* Variant of ykpiv_connect() that accepts a card context obtained externally.
*
* Not for generic use. Use ykpiv_connect() instead.
*
* @param state State handle
* @param context Card context returned from SCardConnect() or equivalent.
* @param card Card ID returned from SCardConnect() or equivalent.
*
* @return Error code
*/
ykpiv_rc ykpiv_connect_with_external_card(ykpiv_state *state, uintptr_t context, uintptr_t card);
/**
* Variant of ykpiv_done() for external cards connected with ykpiv_connect_with_external_card()
*
* Card is not disconnected, unlike with normal calls to ykpiv_done().
*
* @param state State handle
*
* @return Error code
*/
ykpiv_rc ykpiv_done_with_external_card(ykpiv_state *state);
/**
* Variant of ykpiv_verify() that optionally selects the PIV applet first.
*
* @param state State handle
* @param pin PIN code to verify with
* @param pin_len Length of \p pin
* @param tries [out] Number of attempts remaining (if non-NULL)
* @param force_select Whether to select the PIV applet before verifying.
*
* @return Error code
*/
ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries, bool force_select);
/**
* Get serial number
*
* The card must be connected to call this function.
*
* @param state [in] State handle
* @param p_serial [out] uint32 to store retrieved serial number
*
* @return ykpiv_rc error code
*
*/
ykpiv_rc ykpiv_get_serial(ykpiv_state *state, uint32_t* p_serial);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////
////
//// High-level Util API
////
////
//// Util api always allocates data on your behalf, if data = 0, *data != 0,
//// or data_len = 0 an invalid parameter will be returned; to free data, call
//// ykpiv_util_free().
////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
typedef uint32_t ykpiv_devmodel;
/**
* Card identifier
*/
#define YKPIV_CARDID_SIZE 16
typedef struct {
uint8_t data[YKPIV_CARDID_SIZE];
} ykpiv_cardid;
/**
* Card Capability
*/
#define YKPIV_CCCID_SIZE 14
typedef struct {
uint8_t data[YKPIV_CCCID_SIZE];
} ykpiv_cccid;
#pragma pack(push, 1)
typedef struct _ykpiv_key {
uint8_t slot;
uint16_t cert_len;
uint8_t cert[1];
} ykpiv_key;
typedef struct _ykpiv_container {
wchar_t name[40];
uint8_t slot;
uint8_t key_spec;
uint16_t key_size_bits;
uint8_t flags;
uint8_t pin_id;
uint8_t associated_echd_container;
uint8_t cert_fingerprint[20];
} ykpiv_container;
#pragma pack(pop)
typedef enum {
YKPIV_CONFIG_MGM_MANUAL = 0,
YKPIV_CONFIG_MGM_DERIVED = 1,
YKPIV_CONFIG_MGM_PROTECTED = 2
} ykpiv_config_mgm_type;
#pragma pack(push, 1)
typedef struct _ykpiv_config {
uint8_t protected_data_available;
uint8_t puk_blocked;
uint8_t puk_noblock_on_upgrade;
uint32_t pin_last_changed;
ykpiv_config_mgm_type mgm_type;
} ykpiv_config;
typedef struct _ykpiv_mgm {
uint8_t data[24];
} ykpiv_mgm;
#pragma pack(pop)
/**
* Free allocated data
*
* Frees a buffer previously allocated by one of the other \p ykpiv_util functions.
*
* @param state State handle
* @param data Buffer previously allocated by a \p ykpiv_util function
*
* @return ypiv_rc error code
*/
ykpiv_rc ykpiv_util_free(ykpiv_state *state, void *data);
/**
* Returns a list of all saved certificates.
*
* \p data should be freed with \p ykpiv_util_free() after use.
*
* @param state State handle
* @param key_count [out] Number of certificates returned
* @param data [out] Set to a dynamically allocated list of certificates.
* @param data_len [out] Set to size of \p data in bytes
*
* @return Error code
*/
ykpiv_rc ykpiv_util_list_keys(ykpiv_state *state, uint8_t *key_count, ykpiv_key **data, size_t *data_len);
/**
* Read a certificate stored in the given slot
*
* \p data should be freed with \p ykpiv_util_free() after use.
*
* @param state State handle
* @param slot Slot to read from
* @param data Pointer to buffer to store the read data
* @param data_len Pointer to size of input buffer, in bytes. Update to length of read data after call.
*
* @return Error code
*/
ykpiv_rc ykpiv_util_read_cert(ykpiv_state *state, uint8_t slot, uint8_t **data, size_t *data_len);
/**
* Write a certificate to a given slot
*
* \p certinfo should be \p YKPIV_CERTINFO_UNCOMPRESSED for uncompressed certificates, which is the most
* common case, or \p YKPIV_CERTINFO_GZIP if the certificate in \p data is already compressed with gzip.
*
* @param state State handle
* @param slot Slot to write to
* @param data Buffer of data to write
* @param data_len Number of bytes to write
* @param certinfo Hint about type of certificate. Use the \p YKPIV_CERTINFO* defines.
*
* @return Error code
*/
ykpiv_rc ykpiv_util_write_cert(ykpiv_state *state, uint8_t slot, uint8_t *data, size_t data_len, uint8_t certinfo);
/**
* Delete the certificate stored in the given slot
*
* @param state State handle
* @param slot Slot to delete certificate from
*
* @return Error code
*/
ykpiv_rc ykpiv_util_delete_cert(ykpiv_state *state, uint8_t slot);
/**
* Generate key in given slot with specified parameters
*
* \p modulus, \p exp, and \p point should be freed with \p ykpiv_util_free() after use.
*
* If algorithm is RSA1024 or RSA2048, the modulus, modulus_len, exp, and exp_len output parameters must be supplied. They are filled with with public modulus (big-endian), its size, the public exponent (big-endian), and its size respectively.
*
* If algorithm is ECCP256 or ECCP384, the point and point_len output parameters must be supplied. They are filled with the public point (uncompressed octet-string encoded per SEC1 section 2.3.4)
*
* If algorithm is ECCP256, the curve is always ANSI X9.62 Prime 256v1
*
* If algorithm is ECCP384, the curve is always secp384r1
*
* @param state State handle
* @param slot Slot to generate key in
* @param algorithm Key algorithm, specified as one of the \p YKPIV_ALGO_* options
* @param pin_policy Per-slot PIN policy, specified as one of the \p YKPIV_PINPOLICY_* options
* @param touch_policy Per-slot touch policy, specified as one of the \p YKPIV_TOUCHPOLICY_* options.
* @param modulus [out] RSA public modulus (RSA-only)
* @param modulus_len [out] Size of \p modulus (RSA-only)
* @param exp [out] RSA public exponent (RSA-only)
* @param exp_len [out] Size of \p exp (RSA-only)
* @param point [out] Public curve point (ECC-only)
* @param point_len [out] Size of \p point (ECC-only)
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_generate_key(ykpiv_state *state, uint8_t slot, uint8_t algorithm, uint8_t pin_policy, uint8_t touch_policy, uint8_t **modulus, size_t *modulus_len, uint8_t **exp, size_t *exp_len, uint8_t **point, size_t *point_len);
/**
* Get current PIV applet administration configuration state
*
* @param state State handle
* @param config [out] ykpiv_config struct filled with current applet data
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_get_config(ykpiv_state *state, ykpiv_config *config);
/**
* Set last pin changed time to current time
*
* The applet must be authenticated to call this function
*
* @param state State handle
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_set_pin_last_changed(ykpiv_state *state);
/**
* Get Derived MGM key
*
* @param state State handle
* @param pin PIN used to derive mgm key
* @param pin_len Length of pin in bytes
* @param mgm [out] Protected MGM key
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_get_derived_mgm(ykpiv_state *state, const uint8_t *pin, const size_t pin_len, ykpiv_mgm *mgm);
/**
* Get Protected MGM key
*
* The user pin must be verified to call this function
*
* @param state State handle
* @param mgm [out] Protected MGM key
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_get_protected_mgm(ykpiv_state *state, ykpiv_mgm *mgm);
/**
* Set Protected MGM key
*
* The applet must be authenticated and the user pin verified to call this function
*
* If \p mgm is NULL or \p mgm.data is all zeroes, generate MGM, otherwise set specified key.
*
* @param state State handle
* @param mgm [in, out] Input: NULL or new MGM key. Output: Generated MGM key
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_set_protected_mgm(ykpiv_state *state, ykpiv_mgm *mgm);
/**
* Reset PIV applet
*
* The user PIN and PUK must be blocked to call this function.
*
* @param state State handle
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_reset(ykpiv_state *state);
/**
* Get card identifier
*
* Gets the card identifier from the Cardholder Unique Identifier (CHUID).
*
* ID can be set with \p ykpiv_util_set_cardid().
*
* @param state State handle
* @param cardid [out] Unique Card ID stored in the CHUID
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_get_cardid(ykpiv_state *state, ykpiv_cardid *cardid);
/**
* Set card identifier
*
* Set the card identifier in the Cardholder Unique Identifier (CHUID).
*
* The card must be authenticated to call this function.
*
* See also: \p ykpiv_util_set_cccid()
*
* @param state State handle
* @param cardid Unique Card ID to set. If NULL, randomly generate.
*
* @return ypiv_rc error code
*
*/
ykpiv_rc ykpiv_util_set_cardid(ykpiv_state *state, const ykpiv_cardid *cardid);
/**
* Get card capabilities identifier
*
* Gets the card identifier from the Card Capability Container (CCC).
*
* ID can be set with \p ykpiv_util_set_cccid().
*
* @param state State handle
* @param ccc [out] Unique Card ID stored in the CCC
*
* @return ykpiv_rc error code
*/
ykpiv_rc ykpiv_util_get_cccid(ykpiv_state *state, ykpiv_cccid *ccc);
/**
* Set card capabilities identifier
*
* Sets the card identifier in the Card Capability Container (CCC).
*
* The card must be authenticated to call this function.
*
* See also: \p ykpiv_util_set_cardid()
*
* @param state state
* @param ccc Unique Card ID to set. If NULL, randomly generate.
*
* @return ykpiv_rc error code
*
*/
ykpiv_rc ykpiv_util_set_cccid(ykpiv_state *state, const ykpiv_cccid *ccc);
/**
* Get device model
*
* The card must be connected to call this function.
*
* @param state State handle
*
* @return Device model
*
*/
ykpiv_devmodel ykpiv_util_devicemodel(ykpiv_state *state);
/**
* Block PUK
*
* Utility function to block the PUK.
*
* To set the PUK blocked flag in the admin data, the applet must be authenticated.
*
* @param state State handle
*
* @return Error code
*
*/
ykpiv_rc ykpiv_util_block_puk(ykpiv_state *state);
/**
* Object ID of given slot.
*
* @param slot Key slot
*/
uint32_t ykpiv_util_slot_object(uint8_t slot);
ykpiv_rc ykpiv_util_read_mscmap(ykpiv_state *state, ykpiv_container **containers, size_t *n_containers);
ykpiv_rc ykpiv_util_write_mscmap(ykpiv_state *state, ykpiv_container *containers, size_t n_containers);
ykpiv_rc ykpiv_util_read_msroots(ykpiv_state *state, uint8_t **data, size_t *data_len);
ykpiv_rc ykpiv_util_write_msroots(ykpiv_state *state, uint8_t *data, size_t data_len);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////
////
//// Defines
////
////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#define YKPIV_ALGO_TAG 0x80
#define YKPIV_ALGO_3DES 0x03
#define YKPIV_ALGO_RSA1024 0x06
#define YKPIV_ALGO_RSA2048 0x07
#define YKPIV_ALGO_ECCP256 0x11
#define YKPIV_ALGO_ECCP384 0x14
#define YKPIV_KEY_AUTHENTICATION 0x9a
#define YKPIV_KEY_CARDMGM 0x9b
#define YKPIV_KEY_SIGNATURE 0x9c
#define YKPIV_KEY_KEYMGM 0x9d
#define YKPIV_KEY_CARDAUTH 0x9e
#define YKPIV_KEY_RETIRED1 0x82
#define YKPIV_KEY_RETIRED2 0x83
#define YKPIV_KEY_RETIRED3 0x84
#define YKPIV_KEY_RETIRED4 0x85
#define YKPIV_KEY_RETIRED5 0x86
#define YKPIV_KEY_RETIRED6 0x87
#define YKPIV_KEY_RETIRED7 0x88
#define YKPIV_KEY_RETIRED8 0x89
#define YKPIV_KEY_RETIRED9 0x8a
#define YKPIV_KEY_RETIRED10 0x8b
#define YKPIV_KEY_RETIRED11 0x8c
#define YKPIV_KEY_RETIRED12 0x8d
#define YKPIV_KEY_RETIRED13 0x8e
#define YKPIV_KEY_RETIRED14 0x8f
#define YKPIV_KEY_RETIRED15 0x90
#define YKPIV_KEY_RETIRED16 0x91
#define YKPIV_KEY_RETIRED17 0x92
#define YKPIV_KEY_RETIRED18 0x93
#define YKPIV_KEY_RETIRED19 0x94
#define YKPIV_KEY_RETIRED20 0x95
#define YKPIV_KEY_ATTESTATION 0xf9
#define YKPIV_OBJ_CAPABILITY 0x5fc107
#define YKPIV_OBJ_CHUID 0x5fc102
#define YKPIV_OBJ_AUTHENTICATION 0x5fc105 /* cert for 9a key */
#define YKPIV_OBJ_FINGERPRINTS 0x5fc103
#define YKPIV_OBJ_SECURITY 0x5fc106
#define YKPIV_OBJ_FACIAL 0x5fc108
#define YKPIV_OBJ_PRINTED 0x5fc109
#define YKPIV_OBJ_SIGNATURE 0x5fc10a /* cert for 9c key */
#define YKPIV_OBJ_KEY_MANAGEMENT 0x5fc10b /* cert for 9d key */
#define YKPIV_OBJ_CARD_AUTH 0x5fc101 /* cert for 9e key */
#define YKPIV_OBJ_DISCOVERY 0x7e
#define YKPIV_OBJ_KEY_HISTORY 0x5fc10c
#define YKPIV_OBJ_IRIS 0x5fc121
#define YKPIV_OBJ_RETIRED1 0x5fc10d
#define YKPIV_OBJ_RETIRED2 0x5fc10e
#define YKPIV_OBJ_RETIRED3 0x5fc10f
#define YKPIV_OBJ_RETIRED4 0x5fc110
#define YKPIV_OBJ_RETIRED5 0x5fc111
#define YKPIV_OBJ_RETIRED6 0x5fc112
#define YKPIV_OBJ_RETIRED7 0x5fc113
#define YKPIV_OBJ_RETIRED8 0x5fc114
#define YKPIV_OBJ_RETIRED9 0x5fc115
#define YKPIV_OBJ_RETIRED10 0x5fc116
#define YKPIV_OBJ_RETIRED11 0x5fc117
#define YKPIV_OBJ_RETIRED12 0x5fc118
#define YKPIV_OBJ_RETIRED13 0x5fc119
#define YKPIV_OBJ_RETIRED14 0x5fc11a
#define YKPIV_OBJ_RETIRED15 0x5fc11b
#define YKPIV_OBJ_RETIRED16 0x5fc11c
#define YKPIV_OBJ_RETIRED17 0x5fc11d
#define YKPIV_OBJ_RETIRED18 0x5fc11e
#define YKPIV_OBJ_RETIRED19 0x5fc11f
#define YKPIV_OBJ_RETIRED20 0x5fc120
#define YKPIV_OBJ_ATTESTATION 0x5fff01
#define YKPIV_OBJ_MAX_SIZE 3072
#define YKPIV_INS_VERIFY 0x20
#define YKPIV_INS_CHANGE_REFERENCE 0x24
#define YKPIV_INS_RESET_RETRY 0x2c
#define YKPIV_INS_GENERATE_ASYMMETRIC 0x47
#define YKPIV_INS_AUTHENTICATE 0x87
#define YKPIV_INS_GET_DATA 0xcb
#define YKPIV_INS_PUT_DATA 0xdb
#define YKPIV_INS_SELECT_APPLICATION 0xa4
#define YKPIV_INS_GET_RESPONSE_APDU 0xc0
/* sw is status words, see NIST special publication 800-73-4, section 5.6 */
#define SW_SUCCESS 0x9000
#define SW_ERR_SECURITY_STATUS 0x6982
#define SW_ERR_AUTH_BLOCKED 0x6983
#define SW_ERR_INCORRECT_PARAM 0x6a80
/* this is a custom sw for yubikey */
#define SW_ERR_INCORRECT_SLOT 0x6b00
#define SW_ERR_NOT_SUPPORTED 0x6d00
/* Yubico vendor specific instructions */
#define YKPIV_INS_SET_MGMKEY 0xff
#define YKPIV_INS_IMPORT_KEY 0xfe
#define YKPIV_INS_GET_VERSION 0xfd
#define YKPIV_INS_RESET 0xfb
#define YKPIV_INS_SET_PIN_RETRIES 0xfa
#define YKPIV_INS_ATTEST 0xf9
#define YKPIV_INS_GET_SERIAL 0xf8
#define YKPIV_PINPOLICY_TAG 0xaa
#define YKPIV_PINPOLICY_DEFAULT 0
#define YKPIV_PINPOLICY_NEVER 1
#define YKPIV_PINPOLICY_ONCE 2
#define YKPIV_PINPOLICY_ALWAYS 3
#define YKPIV_TOUCHPOLICY_TAG 0xab
#define YKPIV_TOUCHPOLICY_DEFAULT 0
#define YKPIV_TOUCHPOLICY_NEVER 1
#define YKPIV_TOUCHPOLICY_ALWAYS 2
#define YKPIV_TOUCHPOLICY_CACHED 3
#define YKPIV_IS_EC(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384))
#define YKPIV_IS_RSA(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048))
#define YKPIV_RETRIES_DEFAULT 3
#define YKPIV_RETRIES_MAX 0xff
#define YKPIV_CERTINFO_UNCOMPRESSED 0
#define YKPIV_CERTINFO_GZIP 1
#define YKPIV_ATR_NEO_R3 "\x3b\xfc\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x4e\x45\x4f\x72\x33\xe1"
#define YKPIV_ATR_YK4 "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x34\xd4"
#define YKPIV_ATR_YK5_P1 "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x01\x59\x75\x62\x69\x4b\x65\x79\xc1"
#define YKPIV_ATR_YK5 "\x3b\xfd\x13\x00\x00\x81\x31\xfe\x15\x80\x73\xc0\x21\xc0\x57\x59\x75\x62\x69\x4b\x65\x79\x40"
#define DEVTYPE_UNKNOWN 0x00000000
#define DEVTYPE_NEO 0x4E450000 //"NE"
#define DEVTYPE_YK 0x594B0000 //"YK"
#define DEVTYPE_NEOr3 (DEVTYPE_NEO | 0x00007233) //"r3"
#define DEVTYPE_YK4 (DEVTYPE_YK | 0x00000034) // "4"
#define DEVYTPE_YK5 (DEVTYPE_YK | 0x00000035) // "5"
#ifdef __cplusplus
}
#endif
#endif