oxidize: Fix second pass of compile errors and commented-out code
This commit gets the Rust code to compile! 🎉
Additionally, it fixes all of the commented out code that was failing
translation from C due to the use of unions, namely around the APDU
messages.
It does a fair amount of reformatting around branches, with the net
result hopefully being something actually a bit closer to the C code,
and a straightforward list of `if` statements.
It also removes all of the remaining externs that aren't supposed to be
externs, replacing them with a more straightforward usage of the module
system.
Finally it fixes all errors and warnings (relating to e.g. usage of
uninitialized memory), in addition to most clippy lints! (some have
been explicitly disabled)
All that said, it still doesn't do anything: it needs to be wired up to
a PCSC library first before that will be possible. But hey, it compiles!
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
Copyright (c) 2014-2019 Yubico AB, Tony Arcieri
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
//! Application Protocol Data Unit (APDU)
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// Application Protocol Data Unit (APDU).
|
||||
///
|
||||
/// These messages are packets used to communicate with the YubiKey using the
|
||||
/// Chip Card Interface Device (CCID) protocol.
|
||||
#[derive(Clone)]
|
||||
pub struct APDU {
|
||||
/// Instruction class - indicates the type of command, e.g. interindustry or proprietary
|
||||
pub cla: u8,
|
||||
|
||||
/// Instruction code - indicates the specific command, e.g. "write data"
|
||||
pub ins: u8,
|
||||
|
||||
/// Instruction parameter 1 for the command, e.g. offset into file at which to write the data
|
||||
pub p1: u8,
|
||||
|
||||
/// Instruction parameter 2 for the command
|
||||
pub p2: u8,
|
||||
|
||||
/// Length of command - encodes the number of bytes of command data to follow
|
||||
pub lc: u8,
|
||||
|
||||
/// Command data
|
||||
pub data: [u8; 255],
|
||||
}
|
||||
|
||||
impl APDU {
|
||||
/// Get a const pointer to this APDU
|
||||
// TODO(tarcieri): eliminate pointers and use all safe references
|
||||
pub(crate) fn as_ptr(&self) -> *const APDU {
|
||||
self
|
||||
}
|
||||
|
||||
/// Get a mut pointer to this APDU
|
||||
// TODO(tarcieri): eliminate pointers and use all safe references
|
||||
pub(crate) fn as_mut_ptr(&mut self) -> *mut APDU {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for APDU {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cla: 0,
|
||||
ins: 0,
|
||||
p1: 0,
|
||||
p2: 0,
|
||||
lc: 0,
|
||||
data: [0u8; 255],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Zeroize for APDU {
|
||||
fn zeroize(&mut self) {
|
||||
self.cla.zeroize();
|
||||
self.ins.zeroize();
|
||||
self.p1.zeroize();
|
||||
self.p2.zeroize();
|
||||
self.lc.zeroize();
|
||||
self.data.zeroize();
|
||||
}
|
||||
}
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
//! Constant values
|
||||
// TODO(tarcieri): refactor these into enums!
|
||||
|
||||
// Adapted from yubico-piv-tool:
|
||||
// <https://github.com/Yubico/yubico-piv-tool/>
|
||||
//
|
||||
// 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.
|
||||
|
||||
// TODO(tarcieri): document these!
|
||||
#![allow(missing_docs, non_upper_case_globals)]
|
||||
|
||||
pub const szLOG_SOURCE: &str = "yubikey-piv.rs";
|
||||
|
||||
pub const CB_OBJ_MAX: usize = 3063;
|
||||
|
||||
pub const CB_OBJ_TAG_MIN: usize = 2; // 1 byte tag + 1 byte len
|
||||
pub const CB_OBJ_TAG_MAX: usize = (CB_OBJ_TAG_MIN + 2); // 1 byte tag + 3 bytes len
|
||||
|
||||
pub const CB_PIN_MAX: usize = 8;
|
||||
pub const CB_ECC_POINTP256: usize = 65;
|
||||
pub const CB_ECC_POINTP384: usize = 97;
|
||||
|
||||
pub const CHUID_GUID_OFFS: usize = 29;
|
||||
|
||||
pub const CHREF_ACT_CHANGE_PIN: i32 = 0;
|
||||
pub const CHREF_ACT_UNBLOCK_PIN: i32 = 1;
|
||||
pub const CHREF_ACT_CHANGE_PUK: i32 = 2;
|
||||
|
||||
pub const DES_TYPE_3DES: u8 = 1;
|
||||
|
||||
pub const DES_LEN_DES: usize = 8;
|
||||
pub const DES_LEN_3DES: usize = DES_LEN_DES * 3;
|
||||
|
||||
// device types
|
||||
|
||||
pub const DEVTYPE_UNKNOWN: u32 = 0x0000_0000;
|
||||
pub const DEVTYPE_NEO: u32 = 0x4E45_0000; //"NE"
|
||||
pub const DEVTYPE_YK: u32 = 0x594B_0000; //"YK"
|
||||
pub const DEVTYPE_NEOr3: u32 = (DEVTYPE_NEO | 0x0000_7233); //"r3"
|
||||
pub const DEVTYPE_YK4: u32 = (DEVTYPE_YK | 0x0000_0034); // "4"
|
||||
pub const DEVYTPE_YK5: u32 = (DEVTYPE_YK | 0x0000_0035); // "5"
|
||||
|
||||
// sw is status words, see NIST special publication 800-73-4, section 5.6
|
||||
|
||||
pub const SW_SUCCESS: i32 = 0x9000;
|
||||
pub const SW_ERR_SECURITY_STATUS: i32 = 0x6982;
|
||||
pub const SW_ERR_AUTH_BLOCKED: i32 = 0x6983;
|
||||
pub const SW_ERR_INCORRECT_PARAM: i32 = 0x6a80;
|
||||
|
||||
// this is a custom sw for yubikey
|
||||
|
||||
pub const SW_ERR_INCORRECT_SLOT: i32 = 0x6b00;
|
||||
pub const SW_ERR_NOT_SUPPORTED: i32 = 0x6d00;
|
||||
|
||||
pub const TAG_CERT: u8 = 0x70;
|
||||
pub const TAG_CERT_COMPRESS: u8 = 0x71;
|
||||
pub const TAG_CERT_LRC: u8 = 0xFE;
|
||||
pub const TAG_ADMIN: u8 = 0x80;
|
||||
pub const TAG_ADMIN_FLAGS_1: u8 = 0x81;
|
||||
pub const TAG_ADMIN_SALT: u8 = 0x82;
|
||||
pub const TAG_ADMIN_TIMESTAMP: u8 = 0x83;
|
||||
pub const TAG_PROTECTED: u8 = 0x88;
|
||||
pub const TAG_PROTECTED_FLAGS_1: u8 = 0x81;
|
||||
pub const TAG_PROTECTED_MGM: u8 = 0x89;
|
||||
pub const TAG_MSCMAP: u8 = 0x81;
|
||||
pub const TAG_MSROOTS_END: u8 = 0x82;
|
||||
pub const TAG_MSROOTS_MID: u8 = 0x83;
|
||||
|
||||
pub const TAG_RSA_MODULUS: u8 = 0x81;
|
||||
pub const TAG_RSA_EXP: u8 = 0x82;
|
||||
pub const TAG_ECC_POINT: u8 = 0x86;
|
||||
|
||||
pub const YKPIV_ALGO_TAG: u8 = 0x80;
|
||||
pub const YKPIV_ALGO_3DES: u8 = 0x03;
|
||||
pub const YKPIV_ALGO_RSA1024: u8 = 0x06;
|
||||
pub const YKPIV_ALGO_RSA2048: u8 = 0x07;
|
||||
pub const YKPIV_ALGO_ECCP256: u8 = 0x11;
|
||||
pub const YKPIV_ALGO_ECCP384: u8 = 0x14;
|
||||
|
||||
pub const YKPIV_ATR_NEO_R3: &[u8] = b";\xFC\x13\0\0\x811\xFE\x15YubikeyNEOr3\xE1\0";
|
||||
|
||||
pub const YKPIV_CARDID_SIZE: usize = 16;
|
||||
|
||||
pub const YKPIV_CCCID_SIZE: usize = 14;
|
||||
|
||||
pub const YKPIV_CERTINFO_UNCOMPRESSED: u8 = 0;
|
||||
pub const YKPIV_CERTINFO_GZIP: u8 = 1;
|
||||
|
||||
pub const YKPIV_INS_VERIFY: u8 = 0x20;
|
||||
pub const YKPIV_INS_CHANGE_REFERENCE: u8 = 0x24;
|
||||
pub const YKPIV_INS_RESET_RETRY: u8 = 0x2c;
|
||||
pub const YKPIV_INS_GENERATE_ASYMMETRIC: u8 = 0x47;
|
||||
pub const YKPIV_INS_AUTHENTICATE: u8 = 0x87;
|
||||
pub const YKPIV_INS_GET_DATA: u8 = 0xcb;
|
||||
pub const YKPIV_INS_PUT_DATA: u8 = 0xdb;
|
||||
pub const YKPIV_INS_SELECT_APPLICATION: u8 = 0xa4;
|
||||
pub const YKPIV_INS_GET_RESPONSE_APDU: u8 = 0xc0;
|
||||
|
||||
// Yubico vendor specific instructions
|
||||
pub const YKPIV_INS_SET_MGMKEY: u8 = 0xff;
|
||||
pub const YKPIV_INS_IMPORT_KEY: u8 = 0xfe;
|
||||
pub const YKPIV_INS_GET_VERSION: u8 = 0xfd;
|
||||
pub const YKPIV_INS_RESET: u8 = 0xfb;
|
||||
pub const YKPIV_INS_SET_PIN_RETRIES: u8 = 0xfa;
|
||||
pub const YKPIV_INS_ATTEST: u8 = 0xf9;
|
||||
pub const YKPIV_INS_GET_SERIAL: u8 = 0xf8;
|
||||
|
||||
pub const YKPIV_KEY_AUTHENTICATION: u8 = 0x9a;
|
||||
pub const YKPIV_KEY_CARDMGM: u8 = 0x9b;
|
||||
pub const YKPIV_KEY_SIGNATURE: u8 = 0x9c;
|
||||
pub const YKPIV_KEY_KEYMGM: u8 = 0x9d;
|
||||
pub const YKPIV_KEY_CARDAUTH: u8 = 0x9e;
|
||||
pub const YKPIV_KEY_RETIRED1: u8 = 0x82;
|
||||
pub const YKPIV_KEY_RETIRED2: u8 = 0x83;
|
||||
pub const YKPIV_KEY_RETIRED3: u8 = 0x84;
|
||||
pub const YKPIV_KEY_RETIRED4: u8 = 0x85;
|
||||
pub const YKPIV_KEY_RETIRED5: u8 = 0x86;
|
||||
pub const YKPIV_KEY_RETIRED6: u8 = 0x87;
|
||||
pub const YKPIV_KEY_RETIRED7: u8 = 0x88;
|
||||
pub const YKPIV_KEY_RETIRED8: u8 = 0x89;
|
||||
pub const YKPIV_KEY_RETIRED9: u8 = 0x8a;
|
||||
pub const YKPIV_KEY_RETIRED10: u8 = 0x8b;
|
||||
pub const YKPIV_KEY_RETIRED11: u8 = 0x8c;
|
||||
pub const YKPIV_KEY_RETIRED12: u8 = 0x8d;
|
||||
pub const YKPIV_KEY_RETIRED13: u8 = 0x8e;
|
||||
pub const YKPIV_KEY_RETIRED14: u8 = 0x8f;
|
||||
pub const YKPIV_KEY_RETIRED15: u8 = 0x90;
|
||||
pub const YKPIV_KEY_RETIRED16: u8 = 0x91;
|
||||
pub const YKPIV_KEY_RETIRED17: u8 = 0x92;
|
||||
pub const YKPIV_KEY_RETIRED18: u8 = 0x93;
|
||||
pub const YKPIV_KEY_RETIRED19: u8 = 0x94;
|
||||
pub const YKPIV_KEY_RETIRED20: u8 = 0x95;
|
||||
pub const YKPIV_KEY_ATTESTATION: u8 = 0xf9;
|
||||
|
||||
pub const YKPIV_OBJ_CAPABILITY: u32 = 0x005f_c107;
|
||||
pub const YKPIV_OBJ_CHUID: u32 = 0x005f_c102;
|
||||
pub const YKPIV_OBJ_AUTHENTICATION: u32 = 0x005f_c105; // cert for 9a key
|
||||
pub const YKPIV_OBJ_FINGERPRINTS: u32 = 0x005f_c103;
|
||||
pub const YKPIV_OBJ_SECURITY: u32 = 0x005f_c106;
|
||||
pub const YKPIV_OBJ_FACIAL: u32 = 0x005f_c108;
|
||||
pub const YKPIV_OBJ_PRINTED: u32 = 0x005f_c109;
|
||||
pub const YKPIV_OBJ_SIGNATURE: u32 = 0x005f_c10a; // cert for 9c key
|
||||
pub const YKPIV_OBJ_KEY_MANAGEMENT: u32 = 0x005f_c10b; // cert for 9d key
|
||||
pub const YKPIV_OBJ_CARD_AUTH: u32 = 0x005f_c101; // cert for 9e key
|
||||
pub const YKPIV_OBJ_DISCOVERY: u32 = 0x7e;
|
||||
pub const YKPIV_OBJ_KEY_HISTORY: u32 = 0x005f_c10c;
|
||||
pub const YKPIV_OBJ_IRIS: u32 = 0x005f_c121;
|
||||
|
||||
pub const YKPIV_OBJ_RETIRED1: u32 = 0x005f_c10d;
|
||||
pub const YKPIV_OBJ_RETIRED2: u32 = 0x005f_c10e;
|
||||
pub const YKPIV_OBJ_RETIRED3: u32 = 0x005f_c10f;
|
||||
pub const YKPIV_OBJ_RETIRED4: u32 = 0x005f_c110;
|
||||
pub const YKPIV_OBJ_RETIRED5: u32 = 0x005f_c111;
|
||||
pub const YKPIV_OBJ_RETIRED6: u32 = 0x005f_c112;
|
||||
pub const YKPIV_OBJ_RETIRED7: u32 = 0x005f_c113;
|
||||
pub const YKPIV_OBJ_RETIRED8: u32 = 0x005f_c114;
|
||||
pub const YKPIV_OBJ_RETIRED9: u32 = 0x005f_c115;
|
||||
pub const YKPIV_OBJ_RETIRED10: u32 = 0x005f_c116;
|
||||
pub const YKPIV_OBJ_RETIRED11: u32 = 0x005f_c117;
|
||||
pub const YKPIV_OBJ_RETIRED12: u32 = 0x005f_c118;
|
||||
pub const YKPIV_OBJ_RETIRED13: u32 = 0x005f_c119;
|
||||
pub const YKPIV_OBJ_RETIRED14: u32 = 0x005f_c11a;
|
||||
pub const YKPIV_OBJ_RETIRED15: u32 = 0x005f_c11b;
|
||||
pub const YKPIV_OBJ_RETIRED16: u32 = 0x005f_c11c;
|
||||
pub const YKPIV_OBJ_RETIRED17: u32 = 0x005f_c11d;
|
||||
pub const YKPIV_OBJ_RETIRED18: u32 = 0x005f_c11e;
|
||||
pub const YKPIV_OBJ_RETIRED19: u32 = 0x005f_c11f;
|
||||
pub const YKPIV_OBJ_RETIRED20: u32 = 0x005f_c120;
|
||||
|
||||
// Internal object IDs
|
||||
|
||||
pub const YKPIV_OBJ_ADMIN_DATA: u32 = 0x005f_ff00;
|
||||
pub const YKPIV_OBJ_ATTESTATION: u32 = 0x005f_ff01;
|
||||
pub const YKPIV_OBJ_MSCMAP: u32 = 0x005f_ff10;
|
||||
pub const YKPIV_OBJ_MSROOTS1: u32 = 0x005f_ff11;
|
||||
pub const YKPIV_OBJ_MSROOTS2: u32 = 0x005f_ff12;
|
||||
pub const YKPIV_OBJ_MSROOTS3: u32 = 0x005f_ff13;
|
||||
pub const YKPIV_OBJ_MSROOTS4: u32 = 0x005f_ff14;
|
||||
pub const YKPIV_OBJ_MSROOTS5: u32 = 0x005f_ff15;
|
||||
|
||||
pub const YKPIV_OBJ_MAX_SIZE: usize = 3072;
|
||||
|
||||
pub const YKPIV_PINPOLICY_TAG: u8 = 0xaa;
|
||||
pub const YKPIV_PINPOLICY_DEFAULT: u8 = 0;
|
||||
pub const YKPIV_PINPOLICY_NEVER: u8 = 1;
|
||||
pub const YKPIV_PINPOLICY_ONCE: u8 = 2;
|
||||
pub const YKPIV_PINPOLICY_ALWAYS: u8 = 3;
|
||||
|
||||
pub const YKPIV_TOUCHPOLICY_TAG: u8 = 0xab;
|
||||
pub const YKPIV_TOUCHPOLICY_DEFAULT: u8 = 0;
|
||||
pub const YKPIV_TOUCHPOLICY_NEVER: u8 = 1;
|
||||
pub const YKPIV_TOUCHPOLICY_ALWAYS: u8 = 2;
|
||||
pub const YKPIV_TOUCHPOLICY_CACHED: u8 = 3;
|
||||
+96
-68
@@ -1,3 +1,5 @@
|
||||
//! Error types
|
||||
|
||||
// Adapted from yubico-piv-tool:
|
||||
// <https://github.com/Yubico/yubico-piv-tool/>
|
||||
//
|
||||
@@ -30,73 +32,109 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Kinds of errors
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum ErrorKind {
|
||||
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,
|
||||
YKPIV_RANGE_ERROR = -15,
|
||||
YKPIV_NOT_SUPPORTED = -16,
|
||||
/// OK
|
||||
// TODO(tarcieri): replace this with proper result types
|
||||
Ok,
|
||||
|
||||
/// Memory error
|
||||
MemoryError,
|
||||
|
||||
/// PCSC error
|
||||
PcscError,
|
||||
|
||||
/// Size error
|
||||
SizeError,
|
||||
|
||||
/// Applet error
|
||||
AppletError,
|
||||
|
||||
/// Authentication error
|
||||
AuthenticationError,
|
||||
|
||||
/// Randomness error
|
||||
RandomnessError,
|
||||
|
||||
/// Generic error
|
||||
GenericError,
|
||||
|
||||
/// Key error
|
||||
KeyError,
|
||||
|
||||
/// Parse error
|
||||
ParseError,
|
||||
|
||||
/// Wrong PIN
|
||||
WrongPin,
|
||||
|
||||
/// Invalid object
|
||||
InvalidObject,
|
||||
|
||||
/// Algorithm error
|
||||
AlgorithmError,
|
||||
|
||||
/// PIN locked
|
||||
PinLocked,
|
||||
|
||||
/// Argument error
|
||||
ArgumentError,
|
||||
|
||||
/// Range error
|
||||
RangeError,
|
||||
|
||||
/// Not supported
|
||||
NotSupported,
|
||||
}
|
||||
|
||||
impl ErrorKind {
|
||||
/// Name of the error
|
||||
/// Name of the error.
|
||||
///
|
||||
/// These names map to the legacy names from the Yubico C library, to
|
||||
/// assist in web searches for relevant information for these errors.
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
ErrorKind::YKPIV_OK => "YKPIV_OK",
|
||||
ErrorKind::YKPIV_MEMORY_ERROR => "YKPIV_MEMORY_ERROR",
|
||||
ErrorKind::YKPIV_PCSC_ERROR => "YKPIV_PCSC_ERROR",
|
||||
ErrorKind::YKPIV_SIZE_ERROR => "YKPIV_SIZE_ERROR",
|
||||
ErrorKind::YKPIV_APPLET_ERROR => "YKPIV_APPLET_ERROR",
|
||||
ErrorKind::YKPIV_AUTHENTICATION_ERROR => "YKPIV_AUTHENTICATION_ERROR",
|
||||
ErrorKind::YKPIV_RANDOMNESS_ERROR => "YKPIV_RANDOMNESS_ERROR",
|
||||
ErrorKind::YKPIV_GENERIC_ERROR => "YKPIV_GENERIC_ERROR",
|
||||
ErrorKind::YKPIV_KEY_ERROR => "YKPIV_KEY_ERROR",
|
||||
ErrorKind::YKPIV_PARSE_ERROR => "YKPIV_PARSE_ERROR",
|
||||
ErrorKind::YKPIV_WRONG_PIN => "YKPIV_WRONG_PIN",
|
||||
ErrorKind::YKPIV_INVALID_OBJECT => "YKPIV_INVALID_OBJECT",
|
||||
ErrorKind::YKPIV_ALGORITHM_ERROR => "YKPIV_ALGORITHM_ERROR",
|
||||
ErrorKind::YKPIV_PIN_LOCKED => "YKPIV_PIN_LOCKED",
|
||||
ErrorKind::YKPIV_ARGUMENT_ERROR => "YKPIV_ARGUMENT_ERROR",
|
||||
ErrorKind::YKPIV_RANGE_ERROR => "YKPIV_RANGE_ERROR",
|
||||
ErrorKind::YKPIV_NOT_SUPPORTED => "YKPIV_NOT_SUPPORTED",
|
||||
ErrorKind::Ok => "YKPIV_OK",
|
||||
ErrorKind::MemoryError => "YKPIV_MEMORY_ERROR",
|
||||
ErrorKind::PcscError => "YKPIV_PCSC_ERROR",
|
||||
ErrorKind::SizeError => "YKPIV_SIZE_ERROR",
|
||||
ErrorKind::AppletError => "YKPIV_APPLET_ERROR",
|
||||
ErrorKind::AuthenticationError => "YKPIV_AUTHENTICATION_ERROR",
|
||||
ErrorKind::RandomnessError => "YKPIV_RANDOMNESS_ERROR",
|
||||
ErrorKind::GenericError => "YKPIV_GENERIC_ERROR",
|
||||
ErrorKind::KeyError => "YKPIV_KEY_ERROR",
|
||||
ErrorKind::ParseError => "YKPIV_PARSE_ERROR",
|
||||
ErrorKind::WrongPin => "YKPIV_WRONG_PIN",
|
||||
ErrorKind::InvalidObject => "YKPIV_INVALID_OBJECT",
|
||||
ErrorKind::AlgorithmError => "YKPIV_ALGORITHM_ERROR",
|
||||
ErrorKind::PinLocked => "YKPIV_PIN_LOCKED",
|
||||
ErrorKind::ArgumentError => "YKPIV_ARGUMENT_ERROR",
|
||||
ErrorKind::RangeError => "YKPIV_RANGE_ERROR",
|
||||
ErrorKind::NotSupported => "YKPIV_NOT_SUPPORTED",
|
||||
}
|
||||
}
|
||||
|
||||
/// Error message
|
||||
pub fn msg(self) -> &'static str {
|
||||
match self {
|
||||
ErrorKind::YKPIV_OK => "OK",
|
||||
ErrorKind::YKPIV_MEMORY_ERROR => "memory error",
|
||||
ErrorKind::YKPIV_PCSC_ERROR => "PCSC error",
|
||||
ErrorKind::YKPIV_SIZE_ERROR => "size error",
|
||||
ErrorKind::YKPIV_APPLET_ERROR => "applet error",
|
||||
ErrorKind::YKPIV_AUTHENTICATION_ERROR => "authentication error",
|
||||
ErrorKind::YKPIV_RANDOMNESS_ERROR => "randomness error",
|
||||
ErrorKind::YKPIV_GENERIC_ERROR => "generic error",
|
||||
ErrorKind::YKPIV_KEY_ERROR => "key error",
|
||||
ErrorKind::YKPIV_PARSE_ERROR => "parse error",
|
||||
ErrorKind::YKPIV_WRONG_PIN => "wrong pin",
|
||||
ErrorKind::YKPIV_INVALID_OBJECT => "invalid object",
|
||||
ErrorKind::YKPIV_ALGORITHM_ERROR => "algorithm error",
|
||||
ErrorKind::YKPIV_PIN_LOCKED => "PIN locked",
|
||||
ErrorKind::YKPIV_ARGUMENT_ERROR => "argument error",
|
||||
ErrorKind::YKPIV_RANGE_ERROR => "range error",
|
||||
ErrorKind::YKPIV_NOT_SUPPORTED => "not supported",
|
||||
ErrorKind::Ok => "OK",
|
||||
ErrorKind::MemoryError => "memory error",
|
||||
ErrorKind::PcscError => "PCSC error",
|
||||
ErrorKind::SizeError => "size error",
|
||||
ErrorKind::AppletError => "applet error",
|
||||
ErrorKind::AuthenticationError => "authentication error",
|
||||
ErrorKind::RandomnessError => "randomness error",
|
||||
ErrorKind::GenericError => "generic error",
|
||||
ErrorKind::KeyError => "key error",
|
||||
ErrorKind::ParseError => "parse error",
|
||||
ErrorKind::WrongPin => "wrong pin",
|
||||
ErrorKind::InvalidObject => "invalid object",
|
||||
ErrorKind::AlgorithmError => "algorithm error",
|
||||
ErrorKind::PinLocked => "PIN locked",
|
||||
ErrorKind::ArgumentError => "argument error",
|
||||
ErrorKind::RangeError => "range error",
|
||||
ErrorKind::NotSupported => "not supported",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,24 +147,14 @@ impl fmt::Display for ErrorKind {
|
||||
|
||||
impl std::error::Error for ErrorKind {}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Error {
|
||||
pub rc: ErrorKind,
|
||||
pub name: *const u8,
|
||||
pub description: *const u8,
|
||||
}
|
||||
|
||||
impl Clone for Error {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a string representation of this error
|
||||
// TODO(tarcieri): completely replace this with `Display`
|
||||
pub fn ykpiv_strerror(err: ErrorKind) -> &'static str {
|
||||
err.msg()
|
||||
}
|
||||
|
||||
/// Get the name of this error
|
||||
// TODO(tarcieri): completely replace this with debug
|
||||
pub fn ykpiv_strerror_name(err: ErrorKind) -> &'static str {
|
||||
err.name()
|
||||
}
|
||||
|
||||
+226
-460
@@ -1,3 +1,9 @@
|
||||
//! Internal functions (mostly 3DES)
|
||||
|
||||
// TODO(tarcieri): replace OpenSSL extern "C" invocations with `des` crate
|
||||
// - crate: https://crates.io/crates/des
|
||||
// - docs: https://docs.rs/des/0
|
||||
|
||||
// Adapted from yubico-piv-tool:
|
||||
// <https://github.com/Yubico/yubico-piv-tool/>
|
||||
//
|
||||
@@ -28,23 +34,32 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// TODO(tarcieri): investigate and remove dead code
|
||||
#![allow(non_upper_case_globals, dead_code)]
|
||||
#![allow(clippy::missing_safety_doc)]
|
||||
|
||||
use crate::consts::*;
|
||||
use libc::{
|
||||
c_char, c_int, fclose, feof, fgets, fopen, free, getenv, malloc, memcpy, memset, strcasecmp,
|
||||
strcmp, strlen,
|
||||
c_char, c_int, fclose, feof, fgets, fopen, free, getenv, malloc, memcpy, memset, sscanf,
|
||||
strcasecmp, strcmp,
|
||||
};
|
||||
use std::{
|
||||
ffi::{CStr, CString},
|
||||
mem,
|
||||
os::raw::c_void,
|
||||
};
|
||||
use std::ptr;
|
||||
|
||||
extern "C" {
|
||||
fn DES_ecb3_encrypt(
|
||||
input: *mut [u8; 8],
|
||||
output: *mut [u8; 8],
|
||||
ks1: *mut DES_ks,
|
||||
ks2: *mut DES_ks,
|
||||
ks3: *mut DES_ks,
|
||||
ks1: *mut DesSubKey,
|
||||
ks2: *mut DesSubKey,
|
||||
ks3: *mut DesSubKey,
|
||||
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 DES_set_key_unchecked(key: *mut [u8; 8], schedule: *mut DesSubKey);
|
||||
fn PKCS5_PBKDF2_HMAC_SHA1(
|
||||
pass: *const u8,
|
||||
passlen: i32,
|
||||
@@ -55,432 +70,211 @@ extern "C" {
|
||||
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 __tolower(arg1: i32) -> i32;
|
||||
fn __toupper(arg1: i32) -> i32;
|
||||
fn snprintf(__str: *mut u8, __size: usize, __format: *const u8, ...) -> i32;
|
||||
fn sscanf(arg1: *const u8, arg2: *const u8, ...) -> i32;
|
||||
}
|
||||
|
||||
pub 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 "C" fn(*const u8, usize, *mut *const u8) -> i32,
|
||||
pub __sputrune: unsafe extern "C" 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
|
||||
}
|
||||
}
|
||||
|
||||
pub 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)
|
||||
}
|
||||
}
|
||||
|
||||
pub 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)
|
||||
}
|
||||
}
|
||||
|
||||
pub 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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isalnum(mut _c: i32) -> i32 {
|
||||
__istype(_c, (0x100isize | 0x400isize) as (usize))
|
||||
}
|
||||
|
||||
pub fn isalpha(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x100usize)
|
||||
}
|
||||
|
||||
pub fn isblank(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x20000usize)
|
||||
}
|
||||
|
||||
pub fn iscntrl(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x200usize)
|
||||
}
|
||||
|
||||
pub fn isdigit(mut _c: i32) -> i32 {
|
||||
__isctype(_c, 0x400usize)
|
||||
}
|
||||
|
||||
pub fn isgraph(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x800usize)
|
||||
}
|
||||
|
||||
pub fn islower(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x1000usize)
|
||||
}
|
||||
|
||||
pub fn isprint(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x40000usize)
|
||||
}
|
||||
|
||||
pub fn ispunct(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x2000usize)
|
||||
}
|
||||
|
||||
pub fn isspace(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x4000usize)
|
||||
}
|
||||
|
||||
pub fn isupper(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x8000usize)
|
||||
}
|
||||
|
||||
pub fn isxdigit(mut _c: i32) -> i32 {
|
||||
__isctype(_c, 0x10000usize)
|
||||
}
|
||||
|
||||
pub fn toascii(mut _c: i32) -> i32 {
|
||||
_c & 0x7fi32
|
||||
}
|
||||
|
||||
pub fn tolower(mut _c: i32) -> i32 {
|
||||
__tolower(_c)
|
||||
}
|
||||
|
||||
pub fn toupper(mut _c: i32) -> i32 {
|
||||
__toupper(_c)
|
||||
}
|
||||
|
||||
pub fn digittoint(mut _c: i32) -> i32 {
|
||||
__maskrune(_c, 0xfusize)
|
||||
}
|
||||
|
||||
pub fn ishexnumber(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x10000usize)
|
||||
}
|
||||
|
||||
pub fn isideogram(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x80000usize)
|
||||
}
|
||||
|
||||
pub fn isnumber(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x400usize)
|
||||
}
|
||||
|
||||
pub fn isphonogram(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0x200000usize)
|
||||
}
|
||||
|
||||
pub fn isrune(mut _c: i32) -> i32 {
|
||||
__istype(_c, 0xfffffff0usize)
|
||||
}
|
||||
|
||||
pub 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
|
||||
}
|
||||
}
|
||||
|
||||
pub static mut szLOG_SOURCE: *const u8 = (*b"YubiKey PIV Library\0").as_ptr();
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(i32)]
|
||||
/// DES-related errors
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Enum5 {
|
||||
DES_OK = 0i32,
|
||||
DES_INVALID_PARAMETER = -1i32,
|
||||
DES_BUFFER_TOO_SMALL = -2i32,
|
||||
DES_MEMORY_ERROR = -3i32,
|
||||
DES_GENERAL_ERROR = -4i32,
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
pub enum DesErrorKind {
|
||||
/// Ok
|
||||
Ok = 0,
|
||||
|
||||
/// Invalid parameter
|
||||
InvalidParameter = -1,
|
||||
|
||||
/// Buffer too small
|
||||
BufferTooSmall = -2,
|
||||
|
||||
/// Memory error
|
||||
MemoryError = -3,
|
||||
|
||||
/// General error
|
||||
GeneralError = -4,
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
/// 3DES subkeys
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct DES_ks {
|
||||
pub ks: [u8; 16],
|
||||
}
|
||||
pub struct DesSubKey([u8; 16]);
|
||||
|
||||
impl Clone for DES_ks {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
/// 3DES keys
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DesKey {
|
||||
pub ks1: DES_ks,
|
||||
pub ks2: DES_ks,
|
||||
pub ks3: DES_ks,
|
||||
/// subkey 1
|
||||
pub ks1: DesSubKey,
|
||||
|
||||
/// subkey 2
|
||||
pub ks2: DesSubKey,
|
||||
|
||||
/// subkey 3
|
||||
pub ks3: DesSubKey,
|
||||
}
|
||||
|
||||
impl Clone for DesKey {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn des_import_key(
|
||||
type_: i32,
|
||||
mut keyraw: *const u8,
|
||||
/// Import DES key
|
||||
pub unsafe fn des_import_key(
|
||||
key_type: i32,
|
||||
keyraw: *const u8,
|
||||
keyrawlen: usize,
|
||||
mut key: *mut *mut DesKey,
|
||||
) -> 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 {
|
||||
key: *mut *mut DesKey,
|
||||
) -> DesErrorKind {
|
||||
let mut key_tmp = [0u8; 8];
|
||||
let cb_expectedkey: usize;
|
||||
let cb_keysize: usize;
|
||||
|
||||
if key_type != DES_TYPE_3DES as i32 {
|
||||
return DesErrorKind::InvalidParameter;
|
||||
}
|
||||
|
||||
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::<DesKey>()) as (*mut DesKey);
|
||||
*key
|
||||
|
||||
if cb_keysize > 8 {
|
||||
return DesErrorKind::MemoryError;
|
||||
}
|
||||
.is_null()
|
||||
{
|
||||
rc = Enum5::DES_MEMORY_ERROR;
|
||||
_currentBlock = 15;
|
||||
} else {
|
||||
memset(
|
||||
*key as (*mut ::std::os::raw::c_void),
|
||||
0i32,
|
||||
::std::mem::size_of::<DesKey>(),
|
||||
);
|
||||
|
||||
if key.is_null() || keyraw.is_null() || keyrawlen != cb_expectedkey {
|
||||
return DesErrorKind::InvalidParameter;
|
||||
}
|
||||
|
||||
*key = malloc(mem::size_of::<DesKey>()) as (*mut DesKey);
|
||||
|
||||
if (*key).is_null() {
|
||||
return DesErrorKind::MemoryError;
|
||||
}
|
||||
|
||||
memset(*key as (*mut c_void), 0i32, mem::size_of::<DesKey>());
|
||||
|
||||
memcpy(
|
||||
key_tmp.as_mut_ptr() as (*mut ::std::os::raw::c_void),
|
||||
keyraw as (*const ::std::os::raw::c_void),
|
||||
key_tmp.as_mut_ptr() as (*mut c_void),
|
||||
keyraw as (*const c_void),
|
||||
cb_keysize,
|
||||
);
|
||||
DES_set_key_unchecked(
|
||||
&mut key_tmp as (*mut [u8; 8]),
|
||||
&mut (**key).ks1 as (*mut DES_ks),
|
||||
);
|
||||
|
||||
DES_set_key_unchecked(&mut key_tmp, &mut (**key).ks1);
|
||||
|
||||
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),
|
||||
key_tmp.as_mut_ptr() as (*mut c_void),
|
||||
keyraw.add(cb_keysize) as (*const c_void),
|
||||
cb_keysize,
|
||||
);
|
||||
DES_set_key_unchecked(
|
||||
&mut key_tmp as (*mut [u8; 8]),
|
||||
&mut (**key).ks2 as (*mut DES_ks),
|
||||
);
|
||||
|
||||
DES_set_key_unchecked(&mut key_tmp, &mut (**key).ks2);
|
||||
|
||||
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),
|
||||
key_tmp.as_mut_ptr() as (*mut c_void),
|
||||
keyraw.add(2usize.wrapping_mul(cb_keysize)) as (*const 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 {
|
||||
|
||||
DES_set_key_unchecked(&mut key_tmp, &mut (**key).ks3);
|
||||
|
||||
DesErrorKind::Ok
|
||||
}
|
||||
|
||||
/// Destroy DES key
|
||||
pub unsafe fn des_destroy_key(key: *mut DesKey) -> DesErrorKind {
|
||||
if !key.is_null() {
|
||||
des_destroy_key(*key);
|
||||
*key = 0i32 as (*mut ::std::os::raw::c_void) as (*mut DesKey);
|
||||
free(key as (*mut c_void));
|
||||
}
|
||||
}
|
||||
rc
|
||||
|
||||
DesErrorKind::Ok
|
||||
}
|
||||
|
||||
pub fn des_destroy_key(mut key: *mut DesKey) -> Enum5 {
|
||||
if !key.is_null() {
|
||||
free(key as (*mut ::std::os::raw::c_void));
|
||||
/// Encrypt with DES key
|
||||
pub unsafe fn des_encrypt(
|
||||
key: *mut DesKey,
|
||||
input: *const u8,
|
||||
inputlen: usize,
|
||||
out: *mut u8,
|
||||
outlen: *mut usize,
|
||||
) -> DesErrorKind {
|
||||
if key.is_null() || outlen.is_null() || *outlen < inputlen || input.is_null() || out.is_null() {
|
||||
return DesErrorKind::InvalidParameter;
|
||||
}
|
||||
Enum5::DES_OK
|
||||
}
|
||||
|
||||
pub fn des_encrypt(
|
||||
mut key: *mut DesKey,
|
||||
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,
|
||||
input as *mut [u8; 8],
|
||||
out as *mut [u8; 8],
|
||||
&mut (*key).ks1,
|
||||
&mut (*key).ks2,
|
||||
&mut (*key).ks3,
|
||||
1,
|
||||
);
|
||||
}
|
||||
rc
|
||||
|
||||
DesErrorKind::Ok
|
||||
}
|
||||
|
||||
pub fn des_decrypt(
|
||||
mut key: *mut DesKey,
|
||||
mut in_: *const u8,
|
||||
/// Decrypt with DES key
|
||||
pub unsafe fn des_decrypt(
|
||||
key: *mut DesKey,
|
||||
in_: *const u8,
|
||||
inlen: usize,
|
||||
mut out: *mut u8,
|
||||
mut outlen: *mut usize,
|
||||
) -> Enum5 {
|
||||
let mut rc: Enum5 = Enum5::DES_OK;
|
||||
out: *mut u8,
|
||||
outlen: *mut usize,
|
||||
) -> DesErrorKind {
|
||||
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,
|
||||
);
|
||||
return DesErrorKind::InvalidParameter;
|
||||
}
|
||||
rc
|
||||
|
||||
DES_ecb3_encrypt(
|
||||
in_ as *mut [u8; 8],
|
||||
out as *mut [u8; 8],
|
||||
&mut (*key).ks1,
|
||||
&mut (*key).ks2,
|
||||
&mut (*key).ks3,
|
||||
0,
|
||||
);
|
||||
|
||||
DesErrorKind::Ok
|
||||
}
|
||||
|
||||
pub fn yk_des_is_weak_key(mut key: *const u8, cb_key: usize) -> bool {
|
||||
cb_key;
|
||||
/// Is the given DES key weak?
|
||||
pub unsafe fn yk_des_is_weak_key(key: *const u8, _cb_key: usize) -> bool {
|
||||
DES_is_weak_key(key as (*mut [u8; 8])) != 0
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
/// PRNG errors/results
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Enum7 {
|
||||
PRNG_OK = 0i32,
|
||||
PRNG_GENERAL_ERROR = -1i32,
|
||||
pub enum PRngErrorKind {
|
||||
/// Ok
|
||||
Ok = 0,
|
||||
|
||||
/// General error
|
||||
GeneralError = -1,
|
||||
}
|
||||
|
||||
pub 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;
|
||||
/// Generate bytes with the PRNG
|
||||
pub unsafe fn _ykpiv_prng_generate(buffer: *mut u8, cb_req: usize) -> PRngErrorKind {
|
||||
if RAND_bytes(buffer, cb_req as (i32)) != -1 {
|
||||
PRngErrorKind::Ok
|
||||
} else {
|
||||
PRngErrorKind::GeneralError
|
||||
}
|
||||
rc
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
/// PKCS#5 error types
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Enum8 {
|
||||
PKCS5_OK = 0i32,
|
||||
PKCS5_GENERAL_ERROR = -1i32,
|
||||
pub enum Pkcs5ErrorKind {
|
||||
/// OK
|
||||
Ok = 0,
|
||||
|
||||
/// General error
|
||||
GeneralError = -1,
|
||||
}
|
||||
|
||||
pub fn pkcs5_pbkdf2_sha1(
|
||||
mut password: *const u8,
|
||||
/// Decrypt a PKCS#5 key
|
||||
pub unsafe fn pkcs5_pbkdf2_sha1(
|
||||
password: *const u8,
|
||||
cb_password: usize,
|
||||
mut salt: *const u8,
|
||||
salt: *const u8,
|
||||
cb_salt: usize,
|
||||
mut iterations: usize,
|
||||
mut key: *const u8,
|
||||
iterations: usize,
|
||||
key: *const u8,
|
||||
cb_key: usize,
|
||||
) -> Enum8 {
|
||||
let mut rc: Enum8 = Enum8::PKCS5_OK;
|
||||
) -> Pkcs5ErrorKind {
|
||||
PKCS5_PBKDF2_HMAC_SHA1(
|
||||
password,
|
||||
cb_password as (i32),
|
||||
@@ -490,70 +284,55 @@ pub fn pkcs5_pbkdf2_sha1(
|
||||
cb_key as (i32),
|
||||
key as (*mut u8),
|
||||
);
|
||||
rc
|
||||
|
||||
Pkcs5ErrorKind::Ok
|
||||
}
|
||||
|
||||
pub fn _strip_ws(mut sz: *mut c_char) -> *mut c_char {
|
||||
let mut psz_head: *mut c_char = sz;
|
||||
let mut psz_tail: *mut c_char = sz
|
||||
.offset(strlen(sz as *const c_char) 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
|
||||
} = 0;
|
||||
}
|
||||
psz_head
|
||||
/// Strip whitespace
|
||||
// TODO(tarcieri): implement this
|
||||
pub unsafe fn _strip_ws(sz: *mut c_char) -> *mut c_char {
|
||||
sz
|
||||
}
|
||||
|
||||
/// Source of how a setting was configured
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum SettingSource {
|
||||
SETTING_SOURCE_USER,
|
||||
SETTING_SOURCE_ADMIN,
|
||||
SETTING_SOURCE_DEFAULT,
|
||||
/// User-specified setting
|
||||
User,
|
||||
|
||||
/// Admin-specified setting
|
||||
Admin,
|
||||
|
||||
/// Default setting
|
||||
Default,
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
/// Setting booleans
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SettingBool {
|
||||
/// Boolean value
|
||||
pub value: bool,
|
||||
|
||||
/// Source of the configuration setting (user/admin/default)
|
||||
pub source: SettingSource,
|
||||
}
|
||||
|
||||
impl Clone for SettingBool {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn _get_bool_config(mut sz_setting: *const c_char) -> SettingBool {
|
||||
/// Get a boolean config value
|
||||
pub unsafe fn _get_bool_config(sz_setting: *const c_char) -> SettingBool {
|
||||
let mut setting: SettingBool = SettingBool {
|
||||
value: false,
|
||||
source: SettingSource::SETTING_SOURCE_DEFAULT,
|
||||
source: SettingSource::Default,
|
||||
};
|
||||
let mut sz_line = [0u8; 256];
|
||||
let mut psz_name: *mut c_char = ptr::null_mut();
|
||||
let mut psz_value: *mut c_char = ptr::null_mut();
|
||||
let mut psz_name: *mut c_char;
|
||||
let mut psz_value: *mut c_char;
|
||||
let mut sz_name = [0u8; 256];
|
||||
let mut sz_value = [0u8; 256];
|
||||
|
||||
let mut pf = unsafe {
|
||||
fopen(
|
||||
let pf = fopen(
|
||||
b"/etc/yubico/yubikeypiv.conf\0".as_ptr() as *const c_char,
|
||||
b"r\0".as_ptr() as *const c_char,
|
||||
)
|
||||
};
|
||||
);
|
||||
|
||||
if pf.is_null() {
|
||||
return setting;
|
||||
@@ -582,78 +361,65 @@ pub unsafe fn _get_bool_config(mut sz_setting: *const c_char) -> SettingBool {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !(sscanf(
|
||||
sz_line.as_mut_ptr(),
|
||||
(*b"%255[^=]=%255s\0").as_ptr(),
|
||||
if sscanf(
|
||||
sz_line.as_ptr() as *const c_char,
|
||||
b"%255[^=]=%255s\0".as_ptr() as *const c_char,
|
||||
sz_name.as_mut_ptr(),
|
||||
sz_value.as_mut_ptr(),
|
||||
) == 2)
|
||||
) != 2
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
psz_name = _strip_ws(sz_name.as_mut_ptr() as *mut c_char);
|
||||
|
||||
if !(strcasecmp(psz_name as *const c_char, sz_setting as *const c_char) == 0) {
|
||||
if strcasecmp(psz_name, sz_setting) != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
psz_value = _strip_ws(sz_value.as_mut_ptr() as *mut c_char);
|
||||
setting.source = SettingSource::SETTING_SOURCE_ADMIN;
|
||||
setting.value = strcmp(psz_value as *const c_char, b"1\0".as_ptr() as *const c_char) == 0
|
||||
|| strcasecmp(
|
||||
psz_value as *const c_char,
|
||||
b"true\0".as_ptr() as *const c_char,
|
||||
) == 0;
|
||||
setting.source = SettingSource::Admin;
|
||||
setting.value = strcmp(psz_value, b"1\0".as_ptr() as *const c_char) == 0
|
||||
|| strcasecmp(psz_value, b"true\0".as_ptr() as *const c_char) == 0;
|
||||
}
|
||||
|
||||
fclose(pf);
|
||||
setting
|
||||
}
|
||||
|
||||
pub fn _get_bool_env(mut sz_setting: *const c_char) -> SettingBool {
|
||||
/// Get a setting boolean from an environment variable
|
||||
pub unsafe fn _get_bool_env(sz_setting: *const c_char) -> SettingBool {
|
||||
let mut setting: SettingBool = SettingBool {
|
||||
value: false,
|
||||
source: SettingSource::SETTING_SOURCE_DEFAULT,
|
||||
source: SettingSource::Default,
|
||||
};
|
||||
let mut psz_value: *mut c_char = ptr::null_mut();
|
||||
let mut sz_name = [0u8; 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,
|
||||
);
|
||||
let sz_name = CString::new(format!(
|
||||
"YUBIKEY_PIV_{}",
|
||||
CStr::from_ptr(sz_setting).to_string_lossy()
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
psz_value = getenv(sz_name.as_mut_ptr() as *const c_char);
|
||||
let psz_value = getenv(sz_name.as_ptr());
|
||||
|
||||
if !psz_value.is_null() {
|
||||
setting.source = SettingSource::SETTING_SOURCE_USER;
|
||||
setting.value = strcmp(psz_value as *const c_char, b"1\0".as_ptr() as *const c_char) == 0
|
||||
|| strcasecmp(
|
||||
psz_value as *const c_char,
|
||||
b"true\0".as_ptr() as *const c_char,
|
||||
) == 0;
|
||||
setting.source = SettingSource::User;
|
||||
setting.value = strcmp(psz_value, b"1\0".as_ptr() as *const c_char) == 0
|
||||
|| strcasecmp(psz_value, b"true\0".as_ptr() as *const c_char) == 0;
|
||||
}
|
||||
|
||||
setting
|
||||
}
|
||||
|
||||
pub fn setting_get_bool(mut sz_setting: *const c_char, mut def: bool) -> SettingBool {
|
||||
let mut setting: SettingBool = SettingBool {
|
||||
value: def,
|
||||
source: SettingSource::SETTING_SOURCE_DEFAULT,
|
||||
};
|
||||
/// Get a setting boolean
|
||||
pub unsafe fn setting_get_bool(sz_setting: *const c_char, def: bool) -> SettingBool {
|
||||
let mut setting = _get_bool_config(sz_setting);
|
||||
|
||||
setting = _get_bool_config(sz_setting);
|
||||
|
||||
if setting.source == SettingSource::SETTING_SOURCE_DEFAULT {
|
||||
if setting.source == SettingSource::Default {
|
||||
setting = _get_bool_env(sz_setting);
|
||||
}
|
||||
|
||||
if setting.source == SettingSource::SETTING_SOURCE_DEFAULT {
|
||||
if setting.source == SettingSource::Default {
|
||||
setting.value = def;
|
||||
}
|
||||
|
||||
|
||||
+58
-3132
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -90,7 +90,7 @@ static ykpiv_rc _get_metadata_item(uint8_t *data, size_t cb_data, uint8_t tag, u
|
||||
static ykpiv_rc _set_metadata_item(uint8_t *data, size_t *pcb_data, size_t cb_data_max, uint8_t tag, uint8_t *p_item, size_t cb_item);
|
||||
|
||||
static size_t _obj_size_max(ykpiv_state *state) {
|
||||
return (state && state->isNEO) ? CB_OBJ_MAX_NEO : CB_OBJ_MAX;
|
||||
return (state && state->is_neo) ? CB_OBJ_MAX_NEO : CB_OBJ_MAX;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -215,7 +215,7 @@ ykpiv_devmodel ykpiv_util_devicemodel(ykpiv_state *state) {
|
||||
if (!state || !state->context || (state->context == (uintptr_t)-1)) {
|
||||
return DEVTYPE_UNKNOWN;
|
||||
}
|
||||
return (state->isNEO ? DEVTYPE_NEOr3 : DEVTYPE_YK4);
|
||||
return (state->is_neo ? DEVTYPE_NEOr3 : DEVTYPE_YK4);
|
||||
}
|
||||
|
||||
ykpiv_rc ykpiv_util_list_keys(ykpiv_state *state, uint8_t *key_count, ykpiv_key **data, size_t *data_len) {
|
||||
|
||||
+1484
-1997
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -373,7 +373,7 @@ static ykpiv_rc _ykpiv_connect(ykpiv_state *state, uintptr_t context, uintptr_t
|
||||
return YKPIV_PCSC_ERROR;
|
||||
}
|
||||
|
||||
state->isNEO = (((sizeof(YKPIV_ATR_NEO_R3) - 1) == atr_len) && (0 == memcmp(YKPIV_ATR_NEO_R3, atr, atr_len)));
|
||||
state->is_neo = (((sizeof(YKPIV_ATR_NEO_R3) - 1) == atr_len) && (0 == memcmp(YKPIV_ATR_NEO_R3, atr, atr_len)));
|
||||
}
|
||||
|
||||
state->context = context;
|
||||
|
||||
+2549
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user