oxidize: Factor into standard Rust crate structure
- Adds initial `Cargo.toml` (and `Cargo.lock` to `.gitignore`) - Deletes `tool` (it seems hard to `corrode`) - Moves `lib/tests` => `tests` (we should figure out how to translate them) - Moves `lib` => `src` to match Rust conventions - Renames `lib/ykpiv.rs` => `src/lib.rs` to match Rust conventions - Adds copyright from `ykpiv.h` to the top of all `*.rs` files
This commit is contained in:
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// 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.
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(i32)]
|
||||
pub enum Enum2 {
|
||||
YKPIV_OK = 0i32,
|
||||
YKPIV_MEMORY_ERROR = -1i32,
|
||||
YKPIV_PCSC_ERROR = -2i32,
|
||||
YKPIV_SIZE_ERROR = -3i32,
|
||||
YKPIV_APPLET_ERROR = -4i32,
|
||||
YKPIV_AUTHENTICATION_ERROR = -5i32,
|
||||
YKPIV_RANDOMNESS_ERROR = -6i32,
|
||||
YKPIV_GENERIC_ERROR = -7i32,
|
||||
YKPIV_KEY_ERROR = -8i32,
|
||||
YKPIV_PARSE_ERROR = -9i32,
|
||||
YKPIV_WRONG_PIN = -10i32,
|
||||
YKPIV_INVALID_OBJECT = -11i32,
|
||||
YKPIV_ALGORITHM_ERROR = -12i32,
|
||||
YKPIV_PIN_LOCKED = -13i32,
|
||||
YKPIV_ARGUMENT_ERROR = -14i32,
|
||||
YKPIV_RANGE_ERROR = -15i32,
|
||||
YKPIV_NOT_SUPPORTED = -16i32,
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Struct1 {
|
||||
pub rc : Enum2,
|
||||
pub name : *const u8,
|
||||
pub description : *const u8,
|
||||
}
|
||||
|
||||
impl Clone for Struct1 {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
static mut errors
|
||||
: *const Struct1
|
||||
= Enum2::YKPIV_OK as (*const Struct1);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn ykpiv_strerror(mut err : Enum2) -> *const u8 {
|
||||
static mut unknown
|
||||
: *const u8
|
||||
= (*b"Unknown ykpiv error\0").as_ptr();
|
||||
let mut p : *const u8;
|
||||
if -(err as (i32)) < 0i32 || -(err as (i32)) >= ::std::mem::size_of::<*const Struct1>(
|
||||
).wrapping_div(
|
||||
::std::mem::size_of::<Struct1>()
|
||||
) as (i32) {
|
||||
unknown
|
||||
} else {
|
||||
p = (*errors.offset(-(err as (i32)) as (isize))).description;
|
||||
if p.is_null() {
|
||||
p = unknown;
|
||||
}
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn ykpiv_strerror_name(
|
||||
mut err : Enum2
|
||||
) -> *const u8 {
|
||||
if -(err as (i32)) < 0i32 || -(err as (i32)) >= ::std::mem::size_of::<*const Struct1>(
|
||||
).wrapping_div(
|
||||
::std::mem::size_of::<Struct1>()
|
||||
) as (i32) {
|
||||
0i32 as (*mut ::std::os::raw::c_void) as (*const u8)
|
||||
} else {
|
||||
(*errors.offset(-(err as (i32)) as (isize))).name
|
||||
}
|
||||
}
|
||||
+612
@@ -0,0 +1,612 @@
|
||||
#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
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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
|
||||
+780
@@ -0,0 +1,780 @@
|
||||
// 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.
|
||||
|
||||
extern {
|
||||
fn DES_ecb3_encrypt(
|
||||
input : *mut [u8; 8],
|
||||
output : *mut [u8; 8],
|
||||
ks1 : *mut DES_ks,
|
||||
ks2 : *mut DES_ks,
|
||||
ks3 : *mut DES_ks,
|
||||
enc : i32
|
||||
);
|
||||
fn DES_is_weak_key(key : *mut [u8; 8]) -> i32;
|
||||
fn DES_set_key_unchecked(
|
||||
key : *mut [u8; 8], schedule : *mut DES_ks
|
||||
);
|
||||
fn PKCS5_PBKDF2_HMAC_SHA1(
|
||||
pass : *const u8,
|
||||
passlen : i32,
|
||||
salt : *const u8,
|
||||
saltlen : i32,
|
||||
iter : i32,
|
||||
keylen : i32,
|
||||
out : *mut u8
|
||||
) -> i32;
|
||||
fn RAND_bytes(buf : *mut u8, num : i32) -> i32;
|
||||
static mut _DefaultRuneLocale : Struct1;
|
||||
fn __maskrune(arg1 : i32, arg2 : usize) -> i32;
|
||||
fn __swbuf(arg1 : i32, arg2 : *mut __sFILE) -> i32;
|
||||
fn __tolower(arg1 : i32) -> i32;
|
||||
fn __toupper(arg1 : i32) -> i32;
|
||||
fn fclose(arg1 : *mut __sFILE) -> i32;
|
||||
fn feof(arg1 : *mut __sFILE) -> i32;
|
||||
fn fgets(
|
||||
arg1 : *mut u8, arg2 : i32, arg3 : *mut __sFILE
|
||||
) -> *mut u8;
|
||||
fn fopen(
|
||||
__filename : *const u8, __mode : *const u8
|
||||
) -> *mut __sFILE;
|
||||
fn free(arg1 : *mut ::std::os::raw::c_void);
|
||||
fn getenv(arg1 : *const u8) -> *mut u8;
|
||||
fn malloc(__size : usize) -> *mut ::std::os::raw::c_void;
|
||||
fn memcpy(
|
||||
__dst : *mut ::std::os::raw::c_void,
|
||||
__src : *const ::std::os::raw::c_void,
|
||||
__n : usize
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
fn memset(
|
||||
__b : *mut ::std::os::raw::c_void, __c : i32, __len : usize
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
fn snprintf(
|
||||
__str : *mut u8, __size : usize, __format : *const u8, ...
|
||||
) -> i32;
|
||||
fn sscanf(arg1 : *const u8, arg2 : *const u8, ...) -> i32;
|
||||
fn strcasecmp(arg1 : *const u8, arg2 : *const u8) -> i32;
|
||||
fn strcmp(__s1 : *const u8, __s2 : *const u8) -> i32;
|
||||
fn strlen(__s : *const u8) -> usize;
|
||||
}
|
||||
|
||||
enum Union6 {
|
||||
}
|
||||
|
||||
enum __sFILEX {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isascii(mut _c : i32) -> i32 {
|
||||
(_c & !0x7fi32 == 0i32) as (i32)
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Struct3 {
|
||||
pub __min : i32,
|
||||
pub __max : i32,
|
||||
pub __map : i32,
|
||||
pub __types : *mut u32,
|
||||
}
|
||||
|
||||
impl Clone for Struct3 {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Struct2 {
|
||||
pub __nranges : i32,
|
||||
pub __ranges : *mut Struct3,
|
||||
}
|
||||
|
||||
impl Clone for Struct2 {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Struct4 {
|
||||
pub __name : [u8; 14],
|
||||
pub __mask : u32,
|
||||
}
|
||||
|
||||
impl Clone for Struct4 {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Struct1 {
|
||||
pub __magic : [u8; 8],
|
||||
pub __encoding : [u8; 32],
|
||||
pub __sgetrune : unsafe extern fn(*const u8, usize, *mut *const u8) -> i32,
|
||||
pub __sputrune : unsafe extern fn(i32, *mut u8, usize, *mut *mut u8) -> i32,
|
||||
pub __invalid_rune : i32,
|
||||
pub __runetype : [u32; 256],
|
||||
pub __maplower : [i32; 256],
|
||||
pub __mapupper : [i32; 256],
|
||||
pub __runetype_ext : Struct2,
|
||||
pub __maplower_ext : Struct2,
|
||||
pub __mapupper_ext : Struct2,
|
||||
pub __variable : *mut ::std::os::raw::c_void,
|
||||
pub __variable_len : i32,
|
||||
pub __ncharclasses : i32,
|
||||
pub __charclasses : *mut Struct4,
|
||||
}
|
||||
|
||||
impl Clone for Struct1 {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn __istype(mut _c : i32, mut _f : usize) -> i32 {
|
||||
if isascii(_c) != 0 {
|
||||
!(_DefaultRuneLocale.__runetype[
|
||||
_c as (usize)
|
||||
] as (usize) & _f == 0) as (i32)
|
||||
} else {
|
||||
!(__maskrune(_c,_f) == 0) as (i32)
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn __isctype(mut _c : i32, mut _f : usize) -> i32 {
|
||||
if _c < 0i32 || _c >= 256i32 {
|
||||
0i32
|
||||
} else {
|
||||
!(_DefaultRuneLocale.__runetype[
|
||||
_c as (usize)
|
||||
] as (usize) & _f == 0) as (i32)
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn __wcwidth(mut _c : i32) -> i32 {
|
||||
let mut _x : u32;
|
||||
if _c == 0i32 {
|
||||
0i32
|
||||
} else {
|
||||
_x = __maskrune(_c,0xe0000000usize | 0x40000usize) as (u32);
|
||||
(if _x as (usize) & 0xe0000000usize != 0usize {
|
||||
((_x as (usize) & 0xe0000000usize) >> 30i32) as (i32)
|
||||
} else if _x as (usize) & 0x40000usize != 0usize {
|
||||
1i32
|
||||
} else {
|
||||
-1i32
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isalnum(mut _c : i32) -> i32 {
|
||||
__istype(_c,(0x100isize | 0x400isize) as (usize))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isalpha(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x100usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isblank(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x20000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn iscntrl(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x200usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isdigit(mut _c : i32) -> i32 {
|
||||
__isctype(_c,0x400usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isgraph(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x800usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn islower(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x1000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isprint(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x40000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn ispunct(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x2000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isspace(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x4000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isupper(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x8000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isxdigit(mut _c : i32) -> i32 {
|
||||
__isctype(_c,0x10000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn toascii(mut _c : i32) -> i32 { _c & 0x7fi32 }
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn tolower(mut _c : i32) -> i32 { __tolower(_c) }
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn toupper(mut _c : i32) -> i32 { __toupper(_c) }
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn digittoint(mut _c : i32) -> i32 {
|
||||
__maskrune(_c,0xfusize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn ishexnumber(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x10000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isideogram(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x80000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isnumber(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x400usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isphonogram(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x200000usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isrune(mut _c : i32) -> i32 {
|
||||
__istype(_c,0xfffffff0usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn isspecial(mut _c : i32) -> i32 {
|
||||
__istype(_c,0x100000usize)
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct __sbuf {
|
||||
pub _base : *mut u8,
|
||||
pub _size : i32,
|
||||
}
|
||||
|
||||
impl Clone for __sbuf {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct __sFILE {
|
||||
pub _p : *mut u8,
|
||||
pub _r : i32,
|
||||
pub _w : i32,
|
||||
pub _flags : i16,
|
||||
pub _file : i16,
|
||||
pub _bf : __sbuf,
|
||||
pub _lbfsize : i32,
|
||||
pub _cookie : *mut ::std::os::raw::c_void,
|
||||
pub _close : unsafe extern fn(*mut ::std::os::raw::c_void) -> i32,
|
||||
pub _read : unsafe extern fn(*mut ::std::os::raw::c_void, *mut u8, i32) -> i32,
|
||||
pub _seek : unsafe extern fn(*mut ::std::os::raw::c_void, isize, i32) -> isize,
|
||||
pub _write : unsafe extern fn(*mut ::std::os::raw::c_void, *const u8, i32) -> i32,
|
||||
pub _ub : __sbuf,
|
||||
pub _extra : *mut __sFILEX,
|
||||
pub _ur : i32,
|
||||
pub _ubuf : [u8; 3],
|
||||
pub _nbuf : [u8; 1],
|
||||
pub _lb : __sbuf,
|
||||
pub _blksize : i32,
|
||||
pub _offset : isize,
|
||||
}
|
||||
|
||||
impl Clone for __sFILE {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn __sputc(
|
||||
mut _c : i32, mut _p : *mut __sFILE
|
||||
) -> i32 {
|
||||
if {
|
||||
(*_p)._w = (*_p)._w - 1;
|
||||
(*_p)._w
|
||||
} >= 0i32 || (*_p)._w >= (*_p)._lbfsize && (_c as (u8) as (i32) != b'\n' as (i32)) {
|
||||
({
|
||||
let _rhs = _c;
|
||||
let _lhs
|
||||
= &mut *{
|
||||
let _old = (*_p)._p;
|
||||
(*_p)._p = (*_p)._p.offset(1isize);
|
||||
_old
|
||||
};
|
||||
*_lhs = _rhs as (u8);
|
||||
*_lhs
|
||||
}) as (i32)
|
||||
} else {
|
||||
__swbuf(_c,_p)
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut szLOG_SOURCE
|
||||
: *const u8
|
||||
= (*b"YubiKey PIV Library\0").as_ptr();
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(i32)]
|
||||
pub enum Enum5 {
|
||||
DES_OK = 0i32,
|
||||
DES_INVALID_PARAMETER = -1i32,
|
||||
DES_BUFFER_TOO_SMALL = -2i32,
|
||||
DES_MEMORY_ERROR = -3i32,
|
||||
DES_GENERAL_ERROR = -4i32,
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct DES_ks {
|
||||
pub ks : [Union6; 16],
|
||||
}
|
||||
|
||||
impl Clone for DES_ks {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct des_key {
|
||||
pub ks1 : DES_ks,
|
||||
pub ks2 : DES_ks,
|
||||
pub ks3 : DES_ks,
|
||||
}
|
||||
|
||||
impl Clone for des_key {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn des_import_key(
|
||||
type_ : i32,
|
||||
mut keyraw : *const u8,
|
||||
keyrawlen : usize,
|
||||
mut key : *mut *mut des_key
|
||||
) -> Enum5 {
|
||||
let mut _currentBlock;
|
||||
let mut rc : Enum5 = Enum5::DES_OK;
|
||||
let mut cb_expectedkey : usize = (8i32 * 3i32) as (usize);
|
||||
let mut key_tmp : [u8; 8];
|
||||
let mut cb_keysize : usize = 8usize;
|
||||
if type_ == 1i32 {
|
||||
cb_expectedkey = (8i32 * 3i32) as (usize);
|
||||
cb_keysize = 8usize;
|
||||
if cb_keysize > ::std::mem::size_of::<[u8; 8]>() {
|
||||
rc = Enum5::DES_MEMORY_ERROR;
|
||||
_currentBlock = 15;
|
||||
} else if keyraw.is_null() {
|
||||
rc = Enum5::DES_INVALID_PARAMETER;
|
||||
_currentBlock = 15;
|
||||
} else if keyrawlen != cb_expectedkey {
|
||||
rc = Enum5::DES_INVALID_PARAMETER;
|
||||
_currentBlock = 15;
|
||||
} else if key.is_null() {
|
||||
rc = Enum5::DES_INVALID_PARAMETER;
|
||||
_currentBlock = 15;
|
||||
} else if {
|
||||
*key = malloc(::std::mem::size_of::<des_key>()) as (*mut des_key);
|
||||
*key
|
||||
}.is_null(
|
||||
) {
|
||||
rc = Enum5::DES_MEMORY_ERROR;
|
||||
_currentBlock = 15;
|
||||
} else {
|
||||
memset(
|
||||
*key as (*mut ::std::os::raw::c_void),
|
||||
0i32,
|
||||
::std::mem::size_of::<des_key>()
|
||||
);
|
||||
memcpy(
|
||||
key_tmp.as_mut_ptr() as (*mut ::std::os::raw::c_void),
|
||||
keyraw as (*const ::std::os::raw::c_void),
|
||||
cb_keysize
|
||||
);
|
||||
DES_set_key_unchecked(
|
||||
&mut key_tmp as (*mut [u8; 8]),
|
||||
&mut (**key).ks1 as (*mut DES_ks)
|
||||
);
|
||||
memcpy(
|
||||
key_tmp.as_mut_ptr() as (*mut ::std::os::raw::c_void),
|
||||
keyraw.offset(
|
||||
cb_keysize as (isize)
|
||||
) as (*const ::std::os::raw::c_void),
|
||||
cb_keysize
|
||||
);
|
||||
DES_set_key_unchecked(
|
||||
&mut key_tmp as (*mut [u8; 8]),
|
||||
&mut (**key).ks2 as (*mut DES_ks)
|
||||
);
|
||||
memcpy(
|
||||
key_tmp.as_mut_ptr() as (*mut ::std::os::raw::c_void),
|
||||
keyraw.offset(
|
||||
2usize.wrapping_mul(cb_keysize) as (isize)
|
||||
) as (*const ::std::os::raw::c_void),
|
||||
cb_keysize
|
||||
);
|
||||
DES_set_key_unchecked(
|
||||
&mut key_tmp as (*mut [u8; 8]),
|
||||
&mut (**key).ks3 as (*mut DES_ks)
|
||||
);
|
||||
_currentBlock = 17;
|
||||
}
|
||||
} else {
|
||||
rc = Enum5::DES_INVALID_PARAMETER;
|
||||
_currentBlock = 15;
|
||||
}
|
||||
if _currentBlock == 15 {
|
||||
if !key.is_null() {
|
||||
des_destroy_key(*key);
|
||||
*key = 0i32 as (*mut ::std::os::raw::c_void) as (*mut des_key);
|
||||
}
|
||||
}
|
||||
rc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn des_destroy_key(mut key : *mut des_key) -> Enum5 {
|
||||
if !key.is_null() {
|
||||
free(key as (*mut ::std::os::raw::c_void));
|
||||
}
|
||||
Enum5::DES_OK
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn des_encrypt(
|
||||
mut key : *mut des_key,
|
||||
mut in_ : *const u8,
|
||||
inlen : usize,
|
||||
mut out : *mut u8,
|
||||
mut outlen : *mut usize
|
||||
) -> Enum5 {
|
||||
let mut rc : Enum5 = Enum5::DES_OK;
|
||||
if key.is_null() || outlen.is_null(
|
||||
) || *outlen < inlen || in_.is_null() || out.is_null() {
|
||||
rc = Enum5::DES_INVALID_PARAMETER;
|
||||
} else {
|
||||
DES_ecb3_encrypt(
|
||||
in_ as (*mut [u8; 8]),
|
||||
out as (*mut [u8; 8]),
|
||||
&mut (*key).ks1 as (*mut DES_ks),
|
||||
&mut (*key).ks2 as (*mut DES_ks),
|
||||
&mut (*key).ks3 as (*mut DES_ks),
|
||||
1i32
|
||||
);
|
||||
}
|
||||
rc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn des_decrypt(
|
||||
mut key : *mut des_key,
|
||||
mut in_ : *const u8,
|
||||
inlen : usize,
|
||||
mut out : *mut u8,
|
||||
mut outlen : *mut usize
|
||||
) -> Enum5 {
|
||||
let mut rc : Enum5 = Enum5::DES_OK;
|
||||
if key.is_null() || outlen.is_null(
|
||||
) || *outlen < inlen || in_.is_null() || out.is_null() {
|
||||
rc = Enum5::DES_INVALID_PARAMETER;
|
||||
} else {
|
||||
DES_ecb3_encrypt(
|
||||
in_ as (*mut [u8; 8]),
|
||||
out as (*mut [u8; 8]),
|
||||
&mut (*key).ks1 as (*mut DES_ks),
|
||||
&mut (*key).ks2 as (*mut DES_ks),
|
||||
&mut (*key).ks3 as (*mut DES_ks),
|
||||
0i32
|
||||
);
|
||||
}
|
||||
rc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn yk_des_is_weak_key(
|
||||
mut key : *const u8, cb_key : usize
|
||||
) -> bool {
|
||||
cb_key;
|
||||
DES_is_weak_key(key as (*mut [u8; 8])) != 0
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(i32)]
|
||||
pub enum Enum7 {
|
||||
PRNG_OK = 0i32,
|
||||
PRNG_GENERAL_ERROR = -1i32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn _ykpiv_prng_generate(
|
||||
mut buffer : *mut u8, cb_req : usize
|
||||
) -> Enum7 {
|
||||
let mut rc : Enum7 = Enum7::PRNG_OK;
|
||||
if -1i32 == RAND_bytes(buffer,cb_req as (i32)) {
|
||||
rc = Enum7::PRNG_GENERAL_ERROR;
|
||||
}
|
||||
rc
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(i32)]
|
||||
pub enum Enum8 {
|
||||
PKCS5_OK = 0i32,
|
||||
PKCS5_GENERAL_ERROR = -1i32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn pkcs5_pbkdf2_sha1(
|
||||
mut password : *const u8,
|
||||
cb_password : usize,
|
||||
mut salt : *const u8,
|
||||
cb_salt : usize,
|
||||
mut iterations : usize,
|
||||
mut key : *const u8,
|
||||
cb_key : usize
|
||||
) -> Enum8 {
|
||||
let mut rc : Enum8 = Enum8::PKCS5_OK;
|
||||
PKCS5_PBKDF2_HMAC_SHA1(
|
||||
password,
|
||||
cb_password as (i32),
|
||||
salt,
|
||||
cb_salt as (i32),
|
||||
iterations as (i32),
|
||||
cb_key as (i32),
|
||||
key as (*mut u8)
|
||||
);
|
||||
rc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn _strip_ws(mut sz : *mut u8) -> *mut u8 {
|
||||
let mut psz_head : *mut u8 = sz;
|
||||
let mut psz_tail
|
||||
: *mut u8
|
||||
= sz.offset(strlen(sz as (*const u8)) as (isize)).offset(-1isize);
|
||||
'loop1: loop {
|
||||
if isspace(*psz_head as (i32)) == 0 {
|
||||
break;
|
||||
}
|
||||
psz_head = psz_head.offset(1isize);
|
||||
}
|
||||
'loop2: loop {
|
||||
if !(psz_tail >= psz_head && (isspace(*psz_tail as (i32)) != 0)) {
|
||||
break;
|
||||
}
|
||||
*{
|
||||
let _old = psz_tail;
|
||||
psz_tail = psz_tail.offset(-1isize);
|
||||
_old
|
||||
} = b'\0';
|
||||
}
|
||||
psz_head
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(i32)]
|
||||
pub enum _setting_source_t {
|
||||
SETTING_SOURCE_USER,
|
||||
SETTING_SOURCE_ADMIN,
|
||||
SETTING_SOURCE_DEFAULT,
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct _setting_bool_t {
|
||||
pub value : bool,
|
||||
pub source : _setting_source_t,
|
||||
}
|
||||
|
||||
impl Clone for _setting_bool_t {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn _get_bool_config(
|
||||
mut sz_setting : *const u8
|
||||
) -> _setting_bool_t {
|
||||
let mut _currentBlock;
|
||||
let mut setting
|
||||
: _setting_bool_t
|
||||
= _setting_bool_t {
|
||||
value: false,
|
||||
source: _setting_source_t::SETTING_SOURCE_DEFAULT
|
||||
};
|
||||
let mut sz_line : [u8; 256];
|
||||
let mut psz_name : *mut u8 = 0i32 as (*mut u8);
|
||||
let mut psz_value : *mut u8 = 0i32 as (*mut u8);
|
||||
let mut sz_name : [u8; 256];
|
||||
let mut sz_value : [u8; 256];
|
||||
let mut pf : *mut __sFILE = 0i32 as (*mut __sFILE);
|
||||
if !{
|
||||
pf = fopen(
|
||||
(*b"/etc/yubico/yubikeypiv.conf\0").as_ptr(),
|
||||
(*b"r\0").as_ptr()
|
||||
);
|
||||
pf
|
||||
}.is_null(
|
||||
) {
|
||||
_currentBlock = 1;
|
||||
} else {
|
||||
_currentBlock = 10;
|
||||
}
|
||||
'loop1: loop {
|
||||
if _currentBlock == 1 {
|
||||
if feof(pf) == 0 {
|
||||
if fgets(
|
||||
sz_line.as_mut_ptr(),
|
||||
::std::mem::size_of::<[u8; 256]>() as (i32),
|
||||
pf
|
||||
).is_null(
|
||||
) {
|
||||
_currentBlock = 1;
|
||||
continue;
|
||||
}
|
||||
if sz_line[0usize] as (i32) == b'#' as (i32) {
|
||||
_currentBlock = 1;
|
||||
continue;
|
||||
}
|
||||
if sz_line[0usize] as (i32) == b'\r' as (i32) {
|
||||
_currentBlock = 1;
|
||||
continue;
|
||||
}
|
||||
if sz_line[0usize] as (i32) == b'\n' as (i32) {
|
||||
_currentBlock = 1;
|
||||
continue;
|
||||
}
|
||||
if !(sscanf(
|
||||
sz_line.as_mut_ptr() as (*const u8),
|
||||
(*b"%255[^=]=%255s\0").as_ptr(),
|
||||
sz_name.as_mut_ptr(),
|
||||
sz_value.as_mut_ptr()
|
||||
) == 2i32) {
|
||||
_currentBlock = 1;
|
||||
continue;
|
||||
}
|
||||
psz_name = _strip_ws(sz_name.as_mut_ptr());
|
||||
if !(strcasecmp(psz_name as (*const u8),sz_setting) == 0) {
|
||||
_currentBlock = 1;
|
||||
continue;
|
||||
}
|
||||
psz_value = _strip_ws(sz_value.as_mut_ptr());
|
||||
setting.source = _setting_source_t::SETTING_SOURCE_ADMIN;
|
||||
setting.value = strcmp(
|
||||
psz_value as (*const u8),
|
||||
(*b"1\0").as_ptr()
|
||||
) == 0 || strcasecmp(
|
||||
psz_value as (*const u8),
|
||||
(*b"true\0").as_ptr()
|
||||
) == 0;
|
||||
}
|
||||
fclose(pf);
|
||||
_currentBlock = 10;
|
||||
} else {
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn _get_bool_env(
|
||||
mut sz_setting : *const u8
|
||||
) -> _setting_bool_t {
|
||||
let mut setting
|
||||
: _setting_bool_t
|
||||
= _setting_bool_t {
|
||||
value: false,
|
||||
source: _setting_source_t::SETTING_SOURCE_DEFAULT
|
||||
};
|
||||
let mut psz_value
|
||||
: *mut u8
|
||||
= 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8);
|
||||
let mut sz_name : [u8; 256];
|
||||
snprintf(
|
||||
sz_name.as_mut_ptr(),
|
||||
::std::mem::size_of::<[u8; 256]>().wrapping_sub(1usize),
|
||||
(*b"%s%s\0").as_ptr(),
|
||||
(*b"YUBIKEY_PIV_\0").as_ptr(),
|
||||
sz_setting
|
||||
);
|
||||
psz_value = getenv(sz_name.as_mut_ptr() as (*const u8));
|
||||
if !psz_value.is_null() {
|
||||
setting.source = _setting_source_t::SETTING_SOURCE_USER;
|
||||
setting.value = strcmp(
|
||||
psz_value as (*const u8),
|
||||
(*b"1\0").as_ptr()
|
||||
) == 0 || strcasecmp(
|
||||
psz_value as (*const u8),
|
||||
(*b"true\0").as_ptr()
|
||||
) == 0;
|
||||
}
|
||||
setting
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn setting_get_bool(
|
||||
mut sz_setting : *const u8, mut def : bool
|
||||
) -> _setting_bool_t {
|
||||
let mut setting
|
||||
: _setting_bool_t
|
||||
= _setting_bool_t {
|
||||
value: def,
|
||||
source: _setting_source_t::SETTING_SOURCE_DEFAULT
|
||||
};
|
||||
setting = _get_bool_config(sz_setting);
|
||||
if setting.source as (i32) == _setting_source_t::SETTING_SOURCE_DEFAULT as (i32) {
|
||||
setting = _get_bool_env(sz_setting);
|
||||
}
|
||||
if setting.source as (i32) == _setting_source_t::SETTING_SOURCE_DEFAULT as (i32) {
|
||||
setting.value = def;
|
||||
}
|
||||
setting
|
||||
}
|
||||
+3277
File diff suppressed because it is too large
Load Diff
+1681
File diff suppressed because it is too large
Load Diff
+3241
File diff suppressed because it is too large
Load Diff
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
// 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.
|
||||
|
||||
extern {
|
||||
fn strcmp(__s1 : *const u8, __s2 : *const u8) -> i32;
|
||||
fn strcspn(__s : *const u8, __charset : *const u8) -> usize;
|
||||
fn strncmp(__s1 : *const u8, __s2 : *const u8, __n : usize) -> i32;
|
||||
fn strspn(__s : *const u8, __charset : *const u8) -> usize;
|
||||
}
|
||||
|
||||
unsafe extern fn my_strverscmp(
|
||||
mut s1 : *const u8, mut s2 : *const u8
|
||||
) -> i32 {
|
||||
let mut _currentBlock;
|
||||
static mut digits : *const u8 = (*b"0123456789\0").as_ptr();
|
||||
let mut p1 : usize;
|
||||
let mut p2 : usize;
|
||||
p1 = strcspn(s1,digits);
|
||||
p2 = strcspn(s2,digits);
|
||||
'loop1: loop {
|
||||
if !(p1 == p2 && (*s1.offset(
|
||||
p1 as (isize)
|
||||
) as (i32) != b'\0' as (i32)) && (*s2.offset(
|
||||
p2 as (isize)
|
||||
) as (i32) != b'\0' as (i32))) {
|
||||
_currentBlock = 2;
|
||||
break;
|
||||
}
|
||||
let mut ret : i32;
|
||||
let mut lz1 : i32;
|
||||
let mut lz2 : i32;
|
||||
if {
|
||||
ret = strncmp(s1,s2,p1);
|
||||
ret
|
||||
} != 0i32 {
|
||||
_currentBlock = 37;
|
||||
break;
|
||||
}
|
||||
s1 = s1.offset(p1 as (isize));
|
||||
s2 = s2.offset(p2 as (isize));
|
||||
lz1 = {
|
||||
lz2 = 0i32;
|
||||
lz2
|
||||
};
|
||||
if *s1 as (i32) == b'0' as (i32) {
|
||||
lz1 = 1i32;
|
||||
}
|
||||
if *s2 as (i32) == b'0' as (i32) {
|
||||
lz2 = 1i32;
|
||||
}
|
||||
if lz1 > lz2 {
|
||||
_currentBlock = 36;
|
||||
break;
|
||||
}
|
||||
if lz1 < lz2 {
|
||||
_currentBlock = 35;
|
||||
break;
|
||||
}
|
||||
if lz1 == 1i32 {
|
||||
_currentBlock = 11;
|
||||
} else {
|
||||
_currentBlock = 23;
|
||||
}
|
||||
'loop11: loop {
|
||||
if _currentBlock == 11 {
|
||||
if *s1 as (i32) == b'0' as (i32) && (*s2 as (i32) == b'0' as (i32)) {
|
||||
s1 = s1.offset(1isize);
|
||||
s2 = s2.offset(1isize);
|
||||
_currentBlock = 11;
|
||||
} else {
|
||||
p1 = strspn(s1,digits);
|
||||
p2 = strspn(s2,digits);
|
||||
if p1 == 0usize && (p2 > 0usize) {
|
||||
_currentBlock = 33;
|
||||
break 'loop1;
|
||||
}
|
||||
if p2 == 0usize && (p1 > 0usize) {
|
||||
_currentBlock = 32;
|
||||
break 'loop1;
|
||||
}
|
||||
if *s1 as (i32) != *s2 as (i32) && (*s1 as (i32) != b'0' as (i32)) && (*s2 as (i32) != b'0' as (i32)) {
|
||||
if p1 < p2 {
|
||||
_currentBlock = 31;
|
||||
break 'loop1;
|
||||
}
|
||||
if p1 > p2 {
|
||||
_currentBlock = 30;
|
||||
break 'loop1;
|
||||
} else {
|
||||
_currentBlock = 23;
|
||||
}
|
||||
} else {
|
||||
if p1 < p2 {
|
||||
ret = strncmp(s1,s2,p1);
|
||||
} else if p1 > p2 {
|
||||
ret = strncmp(s1,s2,p2);
|
||||
}
|
||||
if ret != 0i32 {
|
||||
_currentBlock = 20;
|
||||
break 'loop1;
|
||||
} else {
|
||||
_currentBlock = 23;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p1 = strspn(s1,digits);
|
||||
p2 = strspn(s2,digits);
|
||||
if p1 < p2 {
|
||||
_currentBlock = 29;
|
||||
break 'loop1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if p1 > p2 {
|
||||
_currentBlock = 28;
|
||||
break;
|
||||
}
|
||||
if {
|
||||
ret = strncmp(s1,s2,p1);
|
||||
ret
|
||||
} != 0i32 {
|
||||
_currentBlock = 27;
|
||||
break;
|
||||
}
|
||||
s1 = s1.offset(p1 as (isize));
|
||||
s2 = s2.offset(p2 as (isize));
|
||||
p1 = strcspn(s1,digits);
|
||||
p2 = strcspn(s2,digits);
|
||||
}
|
||||
if _currentBlock == 2 {
|
||||
strcmp(s1,s2)
|
||||
} else if _currentBlock == 20 {
|
||||
ret
|
||||
} else if _currentBlock == 27 {
|
||||
ret
|
||||
} else if _currentBlock == 28 {
|
||||
1i32
|
||||
} else if _currentBlock == 29 {
|
||||
-1i32
|
||||
} else if _currentBlock == 30 {
|
||||
-1i32
|
||||
} else if _currentBlock == 31 {
|
||||
1i32
|
||||
} else if _currentBlock == 32 {
|
||||
-1i32
|
||||
} else if _currentBlock == 33 {
|
||||
1i32
|
||||
} else if _currentBlock == 35 {
|
||||
1i32
|
||||
} else if _currentBlock == 36 {
|
||||
-1i32
|
||||
} else {
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn ykpiv_check_version(
|
||||
mut req_version : *const u8
|
||||
) -> *const u8 {
|
||||
if req_version.is_null() || my_strverscmp(
|
||||
req_version,
|
||||
(*b"@VERSION@\0").as_ptr()
|
||||
) <= 0i32 {
|
||||
(*b"@VERSION@\0").as_ptr()
|
||||
} else {
|
||||
0i32 as (*mut ::std::os::raw::c_void) as (*const u8)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* 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