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:
-106
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
-143
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
File diff suppressed because it is too large
Load Diff
-702
@@ -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
|
|
||||||
Reference in New Issue
Block a user