diff --git a/lib/error.c b/lib/error.c index 2e56a9f..2e19cd5 100644 --- a/lib/error.c +++ b/lib/error.c @@ -41,7 +41,7 @@ typedef struct const char *description; } err_t; -static const err_t errors[] = { +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"), diff --git a/lib/error.rs b/lib/error.rs new file mode 100644 index 0000000..8a49ffa --- /dev/null +++ b/lib/error.rs @@ -0,0 +1,71 @@ +#[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::() + ) 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::() + ) as (i32) { + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) + } else { + (*errors.offset(-(err as (i32)) as (isize))).name + } +} diff --git a/lib/internal.c b/lib/internal.c index 688cb76..f85acf8 100644 --- a/lib/internal.c +++ b/lib/internal.c @@ -122,7 +122,7 @@ setting_bool_t _get_bool_env(const char *sz_setting); /* log */ -const char szLOG_SOURCE[] = "YubiKey PIV Library"; +const char *szLOG_SOURCE = "YubiKey PIV Library"; /* ** Methods @@ -533,16 +533,16 @@ setting_bool_t _get_bool_config(const char *sz_setting) { char sz_line[256]; char *psz_name = 0; char *psz_value = 0; - char sz_name[256] = { 0 }; - char sz_value[256] = { 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 == '#') continue; - if (*sz_line == '\r') continue; - if (*sz_line == '\n') continue; + 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 */ @@ -569,7 +569,7 @@ setting_bool_t _get_bool_config(const char *sz_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] = { 0 }; + char sz_name[256]; /* XXX REMEMBER TO ZERO */ snprintf(sz_name, sizeof(sz_name) - 1, "%s%s", _ENV_PREFIX, sz_setting); @@ -610,109 +610,3 @@ setting_bool_t setting_get_bool(const char *sz_setting, bool def) { return setting; } - -/* logging */ - -void yc_log_event(uint32_t id, yc_log_level_t level, const char * sz_format, ...) { - char rgsz_message[4096]; - va_list vl; - -#ifdef _WIN32 - HANDLE hLog = NULL; - LPCSTR sz_message = rgsz_message; - WORD w_type = EVENTLOG_SUCCESS; -#else - int priority = LOG_INFO; -#endif - - va_start(vl, sz_format); - -#ifdef _WIN32 - - switch (level) { - case YC_LOG_LEVEL_ERROR: - w_type = EVENTLOG_ERROR_TYPE; - break; - case YC_LOG_LEVEL_WARN: - w_type = EVENTLOG_WARNING_TYPE; - break; - case YC_LOG_LEVEL_INFO: - w_type = EVENTLOG_INFORMATION_TYPE; - break; - case YC_LOG_LEVEL_VERBOSE: - w_type = EVENTLOG_INFORMATION_TYPE; - break; - default: - case YC_LOG_LEVEL_DEBUG: - w_type = EVENTLOG_SUCCESS; - break; - } - - if (!(hLog = RegisterEventSourceA(NULL, szLOG_SOURCE))) { - goto Cleanup; - } - - /* format message */ - - if (FAILED(StringCbVPrintfA( - rgsz_message, - sizeof(rgsz_message), - sz_format, - vl))) { - goto Cleanup; - }; - - // write to the local event log - - ReportEventA( - hLog, - w_type, - 0, - (DWORD)id, - NULL, - 1, - 0, - (LPCSTR *)&sz_message, - NULL); - -#else - - switch (level) { - case YC_LOG_LEVEL_ERROR: - priority = LOG_ERR; - break; - case YC_LOG_LEVEL_WARN: - priority = LOG_WARNING; - break; - case YC_LOG_LEVEL_INFO: - priority = LOG_NOTICE; - break; - case YC_LOG_LEVEL_VERBOSE: - priority = LOG_INFO; - break; - default: - case YC_LOG_LEVEL_DEBUG: - priority = LOG_DEBUG; - break; - } - - if (vsnprintf(rgsz_message, sizeof(rgsz_message), sz_format, vl) < 0) { - goto Cleanup; - } - - openlog(szLOG_SOURCE, LOG_PID | LOG_NDELAY, LOG_USER); - syslog(priority, "%s", rgsz_message); - closelog(); - -#endif - -Cleanup: - - va_end(vl); -#ifdef _WIN32 - if (hLog) { - DeregisterEventSource(hLog); - } -#endif - -} diff --git a/lib/internal.h b/lib/internal.h index 83d1b91..6a8493b 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -71,7 +71,7 @@ extern "C" // 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 CB_OBJ_MAX_YK4 +#define CB_OBJ_MAX 3063 #define CB_BUF_MAX_NEO 2048 #define CB_BUF_MAX_YK4 3072 @@ -236,8 +236,6 @@ typedef enum _yc_log_level_t { YC_LOG_LEVEL_DEBUG } yc_log_level_t; -void yc_log_event(uint32_t id, yc_log_level_t level, const char *sz_format, ...); - #ifdef _WIN32 #include #define yc_memzero SecureZeroMemory diff --git a/lib/internal.rs b/lib/internal.rs new file mode 100644 index 0000000..6d57aaf --- /dev/null +++ b/lib/internal.rs @@ -0,0 +1,753 @@ +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::()) 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::() + ); + 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 +} diff --git a/lib/util.c b/lib/util.c index 3d4384c..fb097e8 100644 --- a/lib/util.c +++ b/lib/util.c @@ -41,6 +41,10 @@ #define MAX(a,b) (a) > (b) ? (a) : (b) #define MIN(a,b) (a) < (b) ? (a) : (b) + +#define SIZEOF_CHUID_TMPL 59 +#define SIZEOF_CCC_TMPL 51 + /* * Format defined in SP-800-73-4, Appendix A, Table 9 * @@ -55,7 +59,7 @@ * - 0x3e: Signature (hard-coded, empty) * - 0xfe: Error Detection Code (hard-coded) */ -const uint8_t CHUID_TMPL[] = { +const uint8_t *CHUID_TMPL = { 0x30, 0x19, 0xd4, 0xe7, 0x39, 0xda, 0x73, 0x9c, 0xed, 0x39, 0xce, 0x73, 0x9d, 0x83, 0x68, 0x58, 0x21, 0x08, 0x42, 0x10, 0x84, 0x21, 0xc8, 0x42, 0x10, 0xc3, 0xeb, 0x34, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -69,7 +73,7 @@ const uint8_t CHUID_TMPL[] = { // - 0xff == Manufacturer ID (dummy) // - 0x02 == Card type (javaCard) // - next 14 bytes: card ID -const uint8_t CCC_TMPL[] = { +const uint8_t *CCC_TMPL = { 0xf0, 0x15, 0xa0, 0x00, 0x00, 0x01, 0x16, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x01, 0x21, 0xf2, 0x01, 0x21, 0xf3, 0x00, 0xf4, 0x01, 0x00, 0xf5, 0x01, 0x10, 0xf6, 0x00, @@ -105,7 +109,7 @@ ykpiv_rc ykpiv_util_get_cardid(ykpiv_state *state, ykpiv_cardid *cardid) { res = _ykpiv_fetch_object(state, YKPIV_OBJ_CHUID, buf, (unsigned long *)&len); if (YKPIV_OK == res) { - if (len != sizeof(CHUID_TMPL)) { + if (len != SIZEOF_CHUID_TMPL) { res = YKPIV_GENERIC_ERROR; } else { @@ -122,7 +126,7 @@ Cleanup: ykpiv_rc ykpiv_util_set_cardid(ykpiv_state *state, const ykpiv_cardid *cardid) { ykpiv_rc res = YKPIV_OK; uint8_t id[YKPIV_CARDID_SIZE]; - uint8_t buf[sizeof(CHUID_TMPL)]; + uint8_t buf[SIZEOF_CHUID_TMPL]; size_t len = 0; if (!state) return YKPIV_GENERIC_ERROR; @@ -139,9 +143,9 @@ ykpiv_rc ykpiv_util_set_cardid(ykpiv_state *state, const ykpiv_cardid *cardid) { if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR; if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup; - memcpy(buf, CHUID_TMPL, sizeof(CHUID_TMPL)); + memcpy(buf, CHUID_TMPL, SIZEOF_CHUID_TMPL); memcpy(buf + CHUID_GUID_OFFS, id, sizeof(id)); - len = sizeof(CHUID_TMPL); + len = SIZEOF_CHUID_TMPL; res = _ykpiv_save_object(state, YKPIV_OBJ_CHUID, buf, len); @@ -163,7 +167,7 @@ ykpiv_rc ykpiv_util_get_cccid(ykpiv_state *state, ykpiv_cccid *ccc) { res = _ykpiv_fetch_object(state, YKPIV_OBJ_CAPABILITY, buf, (unsigned long *)&len); if (YKPIV_OK == res) { - if (len != sizeof(CCC_TMPL)) { + if (len != SIZEOF_CCC_TMPL) { res = YKPIV_GENERIC_ERROR; } else { @@ -180,7 +184,7 @@ Cleanup: ykpiv_rc ykpiv_util_set_cccid(ykpiv_state *state, const ykpiv_cccid *ccc) { ykpiv_rc res = YKPIV_OK; uint8_t id[YKPIV_CCCID_SIZE]; - uint8_t buf[sizeof(CCC_TMPL)]; + uint8_t buf[SIZEOF_CCC_TMPL]; size_t len = 0; if (!state) return YKPIV_GENERIC_ERROR; @@ -197,7 +201,7 @@ ykpiv_rc ykpiv_util_set_cccid(ykpiv_state *state, const ykpiv_cccid *ccc) { if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) return YKPIV_PCSC_ERROR; if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup; - len = sizeof(CCC_TMPL); + len = SIZEOF_CCC_TMPL; memcpy(buf, CCC_TMPL, len); memcpy(buf + CCC_ID_OFFS, id, YKPIV_CCCID_SIZE); res = _ykpiv_save_object(state, YKPIV_OBJ_CAPABILITY, buf, len); @@ -228,7 +232,7 @@ ykpiv_rc ykpiv_util_list_keys(ykpiv_state *state, uint8_t *key_count, ykpiv_key const size_t CB_PAGE = 4096; - const uint8_t SLOTS[] = { + const uint8_t *SLOTS = { YKPIV_KEY_AUTHENTICATION, YKPIV_KEY_SIGNATURE, YKPIV_KEY_KEYMGM, @@ -393,7 +397,7 @@ ykpiv_rc ykpiv_util_delete_cert(ykpiv_state *state, uint8_t slot) { ykpiv_rc ykpiv_util_block_puk(ykpiv_state *state) { ykpiv_rc res = YKPIV_OK; - uint8_t puk[] = { 0x30, 0x42, 0x41, 0x44, 0x46, 0x30, 0x30, 0x44 }; + uint8_t *puk = { 0x30, 0x42, 0x41, 0x44, 0x46, 0x30, 0x30, 0x44 }; int tries = -1; uint8_t data[CB_BUF_MAX]; size_t cb_data = sizeof(data); @@ -716,7 +720,7 @@ ykpiv_rc ykpiv_util_generate_key(ykpiv_state *state, uint8_t slot, uint8_t algor unsigned char in_data[11]; unsigned char *in_ptr = in_data; unsigned char data[1024]; - unsigned char templ[] = { 0, YKPIV_INS_GENERATE_ASYMMETRIC, 0, 0 }; + unsigned char *templ = { 0, YKPIV_INS_GENERATE_ASYMMETRIC, 0, 0 }; unsigned long recv_len = sizeof(data); int sw; uint8_t *ptr_modulus = NULL; @@ -726,17 +730,17 @@ ykpiv_rc ykpiv_util_generate_key(ykpiv_state *state, uint8_t slot, uint8_t algor uint8_t *ptr_point = NULL; size_t cb_point = 0; - setting_bool_t setting_roca = { 0 }; - const char sz_setting_roca[] = "Enable_Unsafe_Keygen_ROCA"; - const char sz_roca_format[] = "YubiKey serial number %u is affected by vulnerability " + setting_bool_t setting_roca; /* XXX was 0 */ + const char *sz_setting_roca = "Enable_Unsafe_Keygen_ROCA"; + const char *sz_roca_format = "YubiKey serial number %u is affected by vulnerability " "CVE-2017-15361 (ROCA) and should be replaced. On-chip key generation %s " "See YSA-2017-01 " "for additional information on device replacement and mitigation assistance.\n"; - const char sz_roca_allow_user[] = "was permitted by an end-user configuration setting, but is not recommended."; - const char sz_roca_allow_admin[] = "was permitted by an administrator configuration setting, but is not recommended."; - const char sz_roca_block_user[] = "was blocked due to an end-user configuration setting."; - const char sz_roca_block_admin[] = "was blocked due to an administrator configuration setting."; - const char sz_roca_default[] = "was permitted by default, but is not recommended. " + const char *sz_roca_allow_user = "was permitted by an end-user configuration setting, but is not recommended."; + const char *sz_roca_allow_admin = "was permitted by an administrator configuration setting, but is not recommended."; + const char *sz_roca_block_user = "was blocked due to an end-user configuration setting."; + const char *sz_roca_block_admin = "was blocked due to an administrator configuration setting."; + const char *sz_roca_default = "was permitted by default, but is not recommended. " "The default behavior will change in a future Yubico release."; if (!state) return YKPIV_ARGUMENT_ERROR; @@ -762,7 +766,7 @@ ykpiv_rc ykpiv_util_generate_key(ykpiv_state *state, uint8_t slot, uint8_t algor } fprintf(stderr, sz_roca_format, state->serial, psz_msg); - yc_log_event(1, setting_roca.value ? YC_LOG_LEVEL_WARN : YC_LOG_LEVEL_ERROR, sz_roca_format, state->serial, psz_msg); + //yc_log_event(1, setting_roca.value ? YC_LOG_LEVEL_WARN : YC_LOG_LEVEL_ERROR, sz_roca_format, state->serial, psz_msg); if (!setting_roca.value) { return YKPIV_NOT_SUPPORTED; @@ -974,7 +978,7 @@ Cleanup: ykpiv_rc ykpiv_util_get_config(ykpiv_state *state, ykpiv_config *config) { ykpiv_rc res = YKPIV_OK; - uint8_t data[CB_BUF_MAX] = { 0 }; + uint8_t data[CB_BUF_MAX]; /* XXX REMEMBER TO ZERO */ size_t cb_data = sizeof(data); uint8_t *p_item = NULL; size_t cb_item = 0; @@ -1052,7 +1056,7 @@ Cleanup: ykpiv_rc ykpiv_util_set_pin_last_changed(ykpiv_state *state) { ykpiv_rc res = YKPIV_OK; ykpiv_rc ykrc = YKPIV_OK; - uint8_t data[CB_BUF_MAX] = { 0 }; + uint8_t data[CB_BUF_MAX]; /* XXX REMEMBER TO ZERO */ size_t cb_data = sizeof(data); time_t tnow = 0; @@ -1087,7 +1091,7 @@ Cleanup: ykpiv_rc ykpiv_util_get_derived_mgm(ykpiv_state *state, const uint8_t *pin, const size_t pin_len, ykpiv_mgm *mgm) { ykpiv_rc res = YKPIV_OK; pkcs5_rc p5rc = PKCS5_OK; - uint8_t data[CB_BUF_MAX] = { 0 }; + uint8_t data[CB_BUF_MAX]; /* XXX REMEMBER TO ZERO */ size_t cb_data = sizeof(data); uint8_t *p_item = NULL; size_t cb_item = 0; @@ -1123,7 +1127,7 @@ Cleanup: ykpiv_rc ykpiv_util_get_protected_mgm(ykpiv_state *state, ykpiv_mgm *mgm) { ykpiv_rc res = YKPIV_OK; - uint8_t data[CB_BUF_MAX] = { 0 }; + uint8_t data[CB_BUF_MAX]; /* XXX REMEMBER TO ZERO */ size_t cb_data = sizeof(data); uint8_t *p_item = NULL; size_t cb_item = 0; @@ -1167,9 +1171,9 @@ ykpiv_rc ykpiv_util_set_protected_mgm(ykpiv_state *state, ykpiv_mgm *mgm) { ykpiv_rc ykrc = YKPIV_OK; prng_rc prngrc = PRNG_OK; bool fGenerate = false; - uint8_t mgm_key[member_size(ykpiv_mgm, data)] = { 0 }; + uint8_t mgm_key[24]; size_t i = 0; - uint8_t data[CB_BUF_MAX] = { 0 }; + uint8_t data[CB_BUF_MAX]; /* XXX REMEMBER TO ZERO */ size_t cb_data = sizeof(data); uint8_t *p_item = NULL; size_t cb_item = 0; @@ -1295,7 +1299,7 @@ Cleanup: } ykpiv_rc ykpiv_util_reset(ykpiv_state *state) { - unsigned char templ[] = {0, YKPIV_INS_RESET, 0, 0}; + unsigned char *templ = {0, YKPIV_INS_RESET, 0, 0}; unsigned char data[0xff]; unsigned long recv_len = sizeof(data); ykpiv_rc res; @@ -1645,7 +1649,7 @@ static ykpiv_rc _read_metadata(ykpiv_state *state, uint8_t tag, uint8_t* data, s */ static ykpiv_rc _write_metadata(ykpiv_state *state, uint8_t tag, uint8_t *data, size_t cb_data) { ykpiv_rc res = YKPIV_OK; - uint8_t buf[CB_OBJ_MAX] = { 0 }; + uint8_t buf[CB_OBJ_MAX]; /* XXX REMEMBER TO ZERO */ uint8_t *pTemp = buf; int obj_id = 0; diff --git a/lib/util.rs b/lib/util.rs new file mode 100644 index 0000000..33f7e02 --- /dev/null +++ b/lib/util.rs @@ -0,0 +1,3214 @@ +extern { + static mut _DefaultRuneLocale : Struct1; + fn __maskrune(arg1 : i32, arg2 : usize) -> i32; + static mut __stderrp : *mut __sFILE; + fn __swbuf(arg1 : i32, arg2 : *mut __sFILE) -> i32; + fn __tolower(arg1 : i32) -> i32; + fn __toupper(arg1 : i32) -> i32; + fn _ykpiv_alloc( + state : *mut ykpiv_state, size : usize + ) -> *mut ::std::os::raw::c_void; + fn _ykpiv_begin_transaction(state : *mut ykpiv_state) -> Enum5; + fn _ykpiv_end_transaction(state : *mut ykpiv_state) -> Enum5; + fn _ykpiv_ensure_application_selected( + state : *mut ykpiv_state + ) -> Enum5; + fn _ykpiv_fetch_object( + state : *mut ykpiv_state, + object_id : i32, + data : *mut u8, + len : *mut usize + ) -> Enum5; + fn _ykpiv_free( + state : *mut ykpiv_state, data : *mut ::std::os::raw::c_void + ); + fn _ykpiv_get_length(buffer : *const u8, len : *mut usize) -> u32; + fn _ykpiv_has_valid_length( + buffer : *const u8, len : usize + ) -> bool; + fn _ykpiv_prng_generate(buffer : *mut u8, cb_req : usize) -> Enum7; + fn _ykpiv_realloc( + state : *mut ykpiv_state, + address : *mut ::std::os::raw::c_void, + size : usize + ) -> *mut ::std::os::raw::c_void; + fn _ykpiv_save_object( + state : *mut ykpiv_state, + object_id : i32, + indata : *mut u8, + len : usize + ) -> Enum5; + fn _ykpiv_set_length(buffer : *mut u8, length : usize) -> u32; + fn _ykpiv_transfer_data( + state : *mut ykpiv_state, + templ : *const u8, + in_data : *const u8, + in_len : isize, + out_data : *mut u8, + out_len : *mut usize, + sw : *mut i32 + ) -> Enum5; + fn fprintf(arg1 : *mut __sFILE, arg2 : *const u8, ...) -> i32; + 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 memmove( + __dst : *mut ::std::os::raw::c_void, + __src : *const ::std::os::raw::c_void, + __len : usize + ) -> *mut ::std::os::raw::c_void; + fn memset_s( + __s : *mut ::std::os::raw::c_void, + __smax : usize, + __c : i32, + __n : usize + ) -> i32; + fn pkcs5_pbkdf2_sha1( + password : *const u8, + cb_password : usize, + salt : *const u8, + cb_salt : usize, + iterations : usize, + key : *const u8, + cb_key : usize + ) -> Enum11; + fn setting_get_bool( + sz_setting : *const u8, f_default : bool + ) -> _setting_bool_t; + fn time(arg1 : *mut isize) -> isize; + fn ykpiv_change_puk( + state : *mut ykpiv_state, + current_puk : *const u8, + current_puk_len : usize, + new_puk : *const u8, + new_puk_len : usize, + tries : *mut i32 + ) -> Enum5; + fn ykpiv_set_mgmkey( + state : *mut ykpiv_state, new_key : *const u8 + ) -> Enum5; + fn ykpiv_transfer_data( + state : *mut ykpiv_state, + templ : *const u8, + in_data : *const u8, + in_len : isize, + out_data : *mut u8, + out_len : *mut usize, + sw : *mut i32 + ) -> Enum5; +} + +enum __sFILEX { +} + +#[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 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) +} + +#[no_mangle] +pub static mut CHUID_TMPL : *const u8 = 0x30i32 as (*const u8); + +#[no_mangle] +pub static mut CCC_TMPL : *const u8 = 0xf0i32 as (*const u8); + +#[derive(Clone, Copy)] +#[repr(i32)] +pub enum Enum5 { + 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 Struct6 { + pub data : [u8; 16], +} + +impl Clone for Struct6 { + fn clone(&self) -> Self { *self } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_get_cardid( + mut state : *mut ykpiv_state, mut cardid : *mut Struct6 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3063]; + let mut len : usize = ::std::mem::size_of::<[u8; 3063]>(); + if cardid.is_null() { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _ykpiv_fetch_object( + state, + 0x5fc102i32, + buf.as_mut_ptr(), + &mut len as (*mut usize) + ); + if Enum5::YKPIV_OK as (i32) == res as (i32) { + if len != 59usize { + res = Enum5::YKPIV_GENERIC_ERROR; + } else { + memcpy( + (*cardid).data.as_mut_ptr() as (*mut ::std::os::raw::c_void), + buf.as_mut_ptr().offset( + 29isize + ) as (*const ::std::os::raw::c_void), + 16usize + ); + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[derive(Clone, Copy)] +#[repr(i32)] +pub enum Enum7 { + PRNG_OK = 0i32, + PRNG_GENERAL_ERROR = -1i32, +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_set_cardid( + mut state : *mut ykpiv_state, mut cardid : *const Struct6 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut id : [u8; 16]; + let mut buf : [u8; 59]; + let mut len : usize = 0usize; + if state.is_null() { + Enum5::YKPIV_GENERIC_ERROR + } else { + if cardid.is_null() { + if Enum7::PRNG_OK as (i32) != _ykpiv_prng_generate( + id.as_mut_ptr(), + ::std::mem::size_of::<[u8; 16]>() + ) as (i32) { + return Enum5::YKPIV_RANDOMNESS_ERROR; + } + } else { + memcpy( + id.as_mut_ptr() as (*mut ::std::os::raw::c_void), + (*cardid).data.as_mut_ptr() as (*const ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 16]>() + ); + } + (if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + memcpy( + buf.as_mut_ptr() as (*mut ::std::os::raw::c_void), + CHUID_TMPL as (*const ::std::os::raw::c_void), + 59usize + ); + memcpy( + buf.as_mut_ptr().offset(29isize) as (*mut ::std::os::raw::c_void), + id.as_mut_ptr() as (*const ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 16]>() + ); + len = 59usize; + res = _ykpiv_save_object(state,0x5fc102i32,buf.as_mut_ptr(),len); + } + _ykpiv_end_transaction(state); + res + }) + } +} + +#[derive(Copy)] +#[repr(C)] +pub struct Struct8 { + pub data : [u8; 14], +} + +impl Clone for Struct8 { + fn clone(&self) -> Self { *self } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_get_cccid( + mut state : *mut ykpiv_state, mut ccc : *mut Struct8 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3063]; + let mut len : usize = ::std::mem::size_of::<[u8; 3063]>(); + if ccc.is_null() { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _ykpiv_fetch_object( + state, + 0x5fc107i32, + buf.as_mut_ptr(), + &mut len as (*mut usize) + ); + if Enum5::YKPIV_OK as (i32) == res as (i32) { + if len != 51usize { + res = Enum5::YKPIV_GENERIC_ERROR; + } else { + memcpy( + (*ccc).data.as_mut_ptr() as (*mut ::std::os::raw::c_void), + buf.as_mut_ptr().offset(9isize) as (*const ::std::os::raw::c_void), + 14usize + ); + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_set_cccid( + mut state : *mut ykpiv_state, mut ccc : *const Struct8 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut id : [u8; 14]; + let mut buf : [u8; 51]; + let mut len : usize = 0usize; + if state.is_null() { + Enum5::YKPIV_GENERIC_ERROR + } else { + if ccc.is_null() { + if Enum7::PRNG_OK as (i32) != _ykpiv_prng_generate( + id.as_mut_ptr(), + ::std::mem::size_of::<[u8; 14]>() + ) as (i32) { + return Enum5::YKPIV_RANDOMNESS_ERROR; + } + } else { + memcpy( + id.as_mut_ptr() as (*mut ::std::os::raw::c_void), + (*ccc).data.as_mut_ptr() as (*const ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 14]>() + ); + } + (if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + len = 51usize; + memcpy( + buf.as_mut_ptr() as (*mut ::std::os::raw::c_void), + CCC_TMPL as (*const ::std::os::raw::c_void), + len + ); + memcpy( + buf.as_mut_ptr().offset(9isize) as (*mut ::std::os::raw::c_void), + id.as_mut_ptr() as (*const ::std::os::raw::c_void), + 14usize + ); + res = _ykpiv_save_object(state,0x5fc107i32,buf.as_mut_ptr(),len); + } + _ykpiv_end_transaction(state); + res + }) + } +} + +#[derive(Copy)] +#[repr(C)] +pub struct ykpiv_allocator { + pub pfn_alloc : unsafe extern fn(*mut ::std::os::raw::c_void, usize) -> *mut ::std::os::raw::c_void, + pub pfn_realloc : unsafe extern fn(*mut ::std::os::raw::c_void, *mut ::std::os::raw::c_void, usize) -> *mut ::std::os::raw::c_void, + pub pfn_free : unsafe extern fn(*mut ::std::os::raw::c_void, *mut ::std::os::raw::c_void), + pub alloc_data : *mut ::std::os::raw::c_void, +} + +impl Clone for ykpiv_allocator { + fn clone(&self) -> Self { *self } +} + +#[derive(Copy)] +#[repr(C)] +pub struct _ykpiv_version_t { + pub major : u8, + pub minor : u8, + pub patch : u8, +} + +impl Clone for _ykpiv_version_t { + fn clone(&self) -> Self { *self } +} + +#[derive(Copy)] +#[repr(C)] +pub struct ykpiv_state { + pub context : i32, + pub card : i32, + pub verbose : i32, + pub pin : *mut u8, + pub allocator : ykpiv_allocator, + pub isNEO : bool, + pub ver : _ykpiv_version_t, + pub serial : u32, +} + +impl Clone for ykpiv_state { + fn clone(&self) -> Self { *self } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_devicemodel( + mut state : *mut ykpiv_state +) -> u32 { + if state.is_null( + ) || (*state).context == 0 || (*state).context as (usize) == -1i32 as (usize) { + 0x0u32 + } else { + (if (*state).isNEO { + 0x4e450000i32 | 0x7233i32 + } else { + 0x594b0000i32 | 0x34i32 + }) as (u32) + } +} + +#[derive(Copy)] +#[repr(C)] +pub struct _ykpiv_key { + pub slot : u8, + pub cert_len : u16, + pub cert : [u8; 1], +} + +impl Clone for _ykpiv_key { + fn clone(&self) -> Self { *self } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_list_keys( + mut state : *mut ykpiv_state, + mut key_count : *mut u8, + mut data : *mut *mut _ykpiv_key, + mut data_len : *mut usize +) -> Enum5 { + let mut _currentBlock; + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut pKey + : *mut _ykpiv_key + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_key); + let mut pData + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut pTemp + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cbData : usize = 0usize; + let mut offset : usize = 0usize; + let mut buf : [u8; 3072]; + let mut cbBuf : usize = 0usize; + let mut i : usize = 0usize; + let mut cbRealloc : usize = 0usize; + let CB_PAGE : usize = 4096usize; + let mut SLOTS : *const u8 = 0x9ai32 as (*const u8); + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut *mut _ykpiv_key) == data || 0i32 as (*mut ::std::os::raw::c_void) as (*mut usize) == data_len || 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == key_count { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + *key_count = 0u8; + *data = 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_key); + *data_len = 0usize; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == { + pData = _ykpiv_alloc( + state, + CB_PAGE + ) as (*mut u8); + pData + } { + res = Enum5::YKPIV_MEMORY_ERROR; + } else { + cbData = CB_PAGE; + i = 0usize; + 'loop5: loop { + if !(i < ::std::mem::size_of::<*const u8>()) { + _currentBlock = 6; + break; + } + cbBuf = ::std::mem::size_of::<[u8; 3072]>(); + res = _read_certificate( + state, + *SLOTS.offset(i as (isize)), + buf.as_mut_ptr(), + &mut cbBuf as (*mut usize) + ); + if res as (i32) == Enum5::YKPIV_OK as (i32) && (cbBuf > 0usize) { + cbRealloc = if ::std::mem::size_of::<_ykpiv_key>().wrapping_add( + cbBuf + ).wrapping_sub( + 1usize + ) > cbData.wrapping_sub(offset) { + (if ::std::mem::size_of::<_ykpiv_key>().wrapping_add( + cbBuf + ).wrapping_sub( + 1usize + ).wrapping_sub( + cbData.wrapping_sub(offset) + ) > CB_PAGE { + ::std::mem::size_of::<_ykpiv_key>().wrapping_add( + cbBuf + ).wrapping_sub( + 1usize + ).wrapping_sub( + cbData.wrapping_sub(offset) + ) + } else { + CB_PAGE + }) + } else { + 0usize + }; + if 0usize != cbRealloc { + if { + pTemp = _ykpiv_realloc( + state, + pData as (*mut ::std::os::raw::c_void), + cbData.wrapping_add(cbRealloc) + ) as (*mut u8); + pTemp + }.is_null( + ) { + _currentBlock = 15; + break; + } + pData = pTemp; + pTemp = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + } + cbData = cbData.wrapping_add(cbRealloc); + pKey = pData.offset(offset as (isize)) as (*mut _ykpiv_key); + (*pKey).slot = *SLOTS.offset(i as (isize)); + (*pKey).cert_len = cbBuf as (u16); + memcpy( + (*pKey).cert.as_mut_ptr() as (*mut ::std::os::raw::c_void), + buf.as_mut_ptr() as (*const ::std::os::raw::c_void), + cbBuf + ); + offset = offset.wrapping_add( + ::std::mem::size_of::<_ykpiv_key>().wrapping_add( + cbBuf + ).wrapping_sub( + 1usize + ) + ); + *key_count = (*key_count as (i32) + 1) as (u8); + } + i = i.wrapping_add(1usize); + } + if _currentBlock == 6 { + *data = pData as (*mut _ykpiv_key); + pData = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + if !data_len.is_null() { + *data_len = offset; + } + res = Enum5::YKPIV_OK; + } else { + res = Enum5::YKPIV_MEMORY_ERROR; + } + } + } + if !pData.is_null() { + _ykpiv_free(state,pData as (*mut ::std::os::raw::c_void)); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_free( + mut state : *mut ykpiv_state, + mut data : *mut ::std::os::raw::c_void +) -> Enum5 { + if data.is_null() { + Enum5::YKPIV_OK + } else if state.is_null() || (*state).allocator.pfn_free == 0 { + Enum5::YKPIV_GENERIC_ERROR + } else { + _ykpiv_free(state,data); + Enum5::YKPIV_OK + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_read_cert( + mut state : *mut ykpiv_state, + mut slot : u8, + mut data : *mut *mut u8, + mut data_len : *mut usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3072]; + let mut cbBuf : usize = ::std::mem::size_of::<[u8; 3072]>(); + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut *mut u8) == data || 0i32 as (*mut ::std::os::raw::c_void) as (*mut usize) == data_len { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + *data = 0i32 as (*mut u8); + *data_len = 0usize; + if Enum5::YKPIV_OK as (i32) == { + res = _read_certificate( + state, + slot, + buf.as_mut_ptr(), + &mut cbBuf as (*mut usize) + ); + res + } as (i32) { + if cbBuf == 0usize { + *data = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *data_len = 0usize; + } else if { + *data = _ykpiv_alloc(state,cbBuf) as (*mut u8); + *data + }.is_null( + ) { + res = Enum5::YKPIV_MEMORY_ERROR; + } else { + memcpy( + *data as (*mut ::std::os::raw::c_void), + buf.as_mut_ptr() as (*const ::std::os::raw::c_void), + cbBuf + ); + *data_len = cbBuf; + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_write_cert( + mut state : *mut ykpiv_state, + mut slot : u8, + mut data : *mut u8, + mut data_len : usize, + mut certinfo : u8 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _write_certificate(state,slot,data,data_len,certinfo); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_delete_cert( + mut state : *mut ykpiv_state, mut slot : u8 +) -> Enum5 { + ykpiv_util_write_cert( + state, + slot, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + 0usize, + 0u8 + ) +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_block_puk( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut _currentBlock; + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut puk : *mut u8 = 0x30i32 as (*mut u8); + let mut tries : i32 = -1i32; + let mut data : [u8; 3072]; + let mut cb_data : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut p_item + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_item : usize = 0usize; + let mut flags : u8 = 0u8; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32) { + _currentBlock = 20; + } else { + _currentBlock = 3; + } + 'loop3: loop { + if _currentBlock == 3 { + if tries != 0i32 { + if Enum5::YKPIV_OK as (i32) == { + res = ykpiv_change_puk( + state, + puk as (*const u8), + ::std::mem::size_of::<*mut u8>(), + puk as (*const u8), + ::std::mem::size_of::<*mut u8>(), + &mut tries as (*mut i32) + ); + res + } as (i32) { + let _rhs = 1; + let _lhs = &mut *puk.offset(0isize); + *_lhs = (*_lhs as (i32) + _rhs) as (u8); + _currentBlock = 3; + } else { + if !(Enum5::YKPIV_PIN_LOCKED as (i32) == res as (i32)) { + _currentBlock = 3; + continue; + } + tries = 0i32; + res = Enum5::YKPIV_OK; + _currentBlock = 3; + } + } else { + if Enum5::YKPIV_OK as (i32) == _read_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ) as (i32) { + if Enum5::YKPIV_OK as (i32) == _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x81u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ) as (i32) { + if ::std::mem::size_of::() == cb_item { + memcpy( + &mut flags as (*mut u8) as (*mut ::std::os::raw::c_void), + p_item as (*const ::std::os::raw::c_void), + cb_item + ); + } else if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"admin flags exist, but are incorrect size = %lu\0").as_ptr( + ), + cb_item + ); + } + } + } + flags = (flags as (i32) | 0x1i32) as (u8); + if Enum5::YKPIV_OK as (i32) != _set_metadata_item( + data.as_mut_ptr(), + &mut cb_data as (*mut usize), + 3063usize, + 0x81u8, + &mut flags as (*mut u8), + ::std::mem::size_of::() + ) as (i32) { + if (*state).verbose == 0 { + _currentBlock = 20; + continue; + } + fprintf(__stderrp,(*b"could not set admin flags\0").as_ptr()); + _currentBlock = 20; + } else { + if !(Enum5::YKPIV_OK as (i32) != _write_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + cb_data + ) as (i32)) { + _currentBlock = 20; + continue; + } + if (*state).verbose == 0 { + _currentBlock = 20; + continue; + } + fprintf(__stderrp,(*b"could not write admin metadata\0").as_ptr()); + _currentBlock = 20; + } + } + } else { + _ykpiv_end_transaction(state); + return res; + } + } + } +} + +#[derive(Copy)] +#[repr(C)] +pub struct _ykpiv_container { + pub name : [i32; 40], + pub slot : u8, + pub key_spec : u8, + pub key_size_bits : u16, + pub flags : u8, + pub pin_id : u8, + pub associated_echd_container : u8, + pub cert_fingerprint : [u8; 20], +} + +impl Clone for _ykpiv_container { + fn clone(&self) -> Self { *self } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_read_mscmap( + mut state : *mut ykpiv_state, + mut containers : *mut *mut _ykpiv_container, + mut n_containers : *mut usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3072]; + let mut cbBuf : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut len : usize = 0usize; + let mut ptr + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut *mut _ykpiv_container) == containers || 0i32 as (*mut ::std::os::raw::c_void) as (*mut usize) == n_containers { + res = Enum5::YKPIV_GENERIC_ERROR; + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + return Enum5::YKPIV_PCSC_ERROR; + } else if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + *containers = 0i32 as (*mut _ykpiv_container); + *n_containers = 0usize; + if Enum5::YKPIV_OK as (i32) == { + res = _ykpiv_fetch_object( + state, + 0x5fff10i32, + buf.as_mut_ptr(), + &mut cbBuf as (*mut usize) + ); + res + } as (i32) { + ptr = buf.as_mut_ptr(); + if cbBuf < 2usize { + res = Enum5::YKPIV_OK; + } else if *{ + let _old = ptr; + ptr = ptr.offset(1isize); + _old + } as (i32) == 0x81i32 { + ptr = ptr.offset( + _ykpiv_get_length( + ptr as (*const u8), + &mut len as (*mut usize) + ) as (usize) as (isize) + ); + if len > cbBuf.wrapping_sub( + ((ptr as (isize)).wrapping_sub( + buf.as_mut_ptr() as (isize) + ) / ::std::mem::size_of::() as (isize)) as (usize) + ) { + res = Enum5::YKPIV_OK; + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_container) == { + *containers = _ykpiv_alloc( + state, + len + ) as (*mut _ykpiv_container); + *containers + } { + res = Enum5::YKPIV_MEMORY_ERROR; + } else { + memcpy( + *containers as (*mut ::std::os::raw::c_void), + ptr as (*const ::std::os::raw::c_void), + len + ); + *n_containers = len.wrapping_div( + ::std::mem::size_of::<_ykpiv_container>() + ); + } + } + } + } + _ykpiv_end_transaction(state); + res +} + +unsafe extern fn _obj_size_max( + mut state : *mut ykpiv_state +) -> usize { + (if !state.is_null() && (*state).isNEO { + 2048i32 - 9i32 + } else { + 3063i32 + }) as (usize) +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_write_mscmap( + mut state : *mut ykpiv_state, + mut containers : *mut _ykpiv_container, + mut n_containers : usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3063]; + let mut offset : usize = 0usize; + let mut req_len : usize = 0usize; + let mut data_len + : usize + = n_containers.wrapping_mul( + ::std::mem::size_of::<_ykpiv_container>() + ); + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_container) == containers || 0usize == n_containers { + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_container) != containers || 0usize != n_containers { + res = Enum5::YKPIV_GENERIC_ERROR; + } else { + res = _ykpiv_save_object( + state, + 0x5fff10i32, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + 0usize + ); + } + } else { + req_len = 1usize.wrapping_add( + _ykpiv_set_length(buf.as_mut_ptr(),data_len) as (usize) + ).wrapping_add( + data_len + ); + if req_len > _obj_size_max(state) { + res = Enum5::YKPIV_SIZE_ERROR; + } else { + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = 0x81u8; + offset = offset.wrapping_add( + _ykpiv_set_length( + buf.as_mut_ptr().offset(offset as (isize)), + data_len + ) as (usize) + ); + memcpy( + buf.as_mut_ptr().offset( + offset as (isize) + ) as (*mut ::std::os::raw::c_void), + containers as (*mut u8) as (*const ::std::os::raw::c_void), + data_len + ); + offset = offset.wrapping_add(data_len); + res = _ykpiv_save_object( + state, + 0x5fff10i32, + buf.as_mut_ptr(), + offset + ); + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_read_msroots( + mut state : *mut ykpiv_state, + mut data : *mut *mut u8, + mut data_len : *mut usize +) -> Enum5 { + let mut _currentBlock; + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3072]; + let mut cbBuf : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut len : usize = 0usize; + let mut ptr + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut object_id : i32 = 0i32; + let mut tag : u8 = 0u8; + let mut pData + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut pTemp + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cbData : usize = 0usize; + let mut cbRealloc : usize = 0usize; + let mut offset : usize = 0usize; + if data.is_null() || data_len.is_null() { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + *data = 0i32 as (*mut u8); + *data_len = 0usize; + cbData = _obj_size_max(state); + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == { + pData = _ykpiv_alloc( + state, + cbData + ) as (*mut u8); + pData + } { + res = Enum5::YKPIV_MEMORY_ERROR; + } else { + object_id = 0x5fff11i32; + 'loop5: loop { + if !(object_id <= 0x5fff15i32) { + _currentBlock = 15; + break; + } + cbBuf = ::std::mem::size_of::<[u8; 3072]>(); + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_fetch_object( + state, + object_id, + buf.as_mut_ptr(), + &mut cbBuf as (*mut usize) + ); + res + } as (i32) { + _currentBlock = 21; + break; + } + ptr = buf.as_mut_ptr(); + if cbBuf < 2usize { + _currentBlock = 19; + break; + } + tag = *{ + let _old = ptr; + ptr = ptr.offset(1isize); + _old + }; + if 0x83i32 != tag as (i32) && (0x82i32 != tag as (i32)) || 0x5fff15i32 == object_id && (0x82i32 != tag as (i32)) { + _currentBlock = 18; + break; + } + ptr = ptr.offset( + _ykpiv_get_length( + ptr as (*const u8), + &mut len as (*mut usize) + ) as (isize) + ); + if len > cbBuf.wrapping_sub( + ((ptr as (isize)).wrapping_sub( + buf.as_mut_ptr() as (isize) + ) / ::std::mem::size_of::() as (isize)) as (usize) + ) { + _currentBlock = 17; + break; + } + cbRealloc = if len > cbData.wrapping_sub(offset) { + len.wrapping_sub(cbData.wrapping_sub(offset)) + } else { + 0usize + }; + if 0usize != cbRealloc { + if { + pTemp = _ykpiv_realloc( + state, + pData as (*mut ::std::os::raw::c_void), + cbData.wrapping_add(cbRealloc) + ) as (*mut u8); + pTemp + }.is_null( + ) { + _currentBlock = 16; + break; + } + pData = pTemp; + pTemp = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + } + cbData = cbData.wrapping_add(cbRealloc); + memcpy( + pData.offset(offset as (isize)) as (*mut ::std::os::raw::c_void), + ptr as (*const ::std::os::raw::c_void), + len + ); + offset = offset.wrapping_add(len); + if 0x82i32 == tag as (i32) { + _currentBlock = 15; + break; + } + object_id = object_id + 1; + } + if _currentBlock == 21 { + } else if _currentBlock == 15 { + *data = pData; + pData = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *data_len = offset; + res = Enum5::YKPIV_OK; + } else if _currentBlock == 16 { + res = Enum5::YKPIV_MEMORY_ERROR; + } else if _currentBlock == 17 { + res = Enum5::YKPIV_OK; + } else if _currentBlock == 18 { + res = Enum5::YKPIV_OK; + } else { + res = Enum5::YKPIV_OK; + } + } + } + if !pData.is_null() { + _ykpiv_free(state,pData as (*mut ::std::os::raw::c_void)); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_write_msroots( + mut state : *mut ykpiv_state, + mut data : *mut u8, + mut data_len : usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3063]; + let mut offset : usize = 0usize; + let mut data_offset : usize = 0usize; + let mut data_chunk : usize = 0usize; + let mut n_objs : usize = 0usize; + let mut i : u32 = 0u32; + let mut cb_obj_max : usize = _obj_size_max(state); + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == data || 0usize == data_len { + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) != data || 0usize != data_len { + res = Enum5::YKPIV_GENERIC_ERROR; + } else { + res = _ykpiv_save_object( + state, + 0x5fff11i32, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + 0usize + ); + } + } else { + n_objs = data_len.wrapping_div( + cb_obj_max.wrapping_sub((2i32 + 2i32) as (usize)) + ).wrapping_add( + 1usize + ); + if n_objs > 5usize { + res = Enum5::YKPIV_SIZE_ERROR; + } else { + i = 0u32; + 'loop5: loop { + if !(i as (usize) < n_objs) { + break; + } + offset = 0usize; + data_chunk = if cb_obj_max.wrapping_sub( + (2i32 + 2i32) as (usize) + ) < data_len.wrapping_sub(data_offset) { + cb_obj_max.wrapping_sub((2i32 + 2i32) as (usize)) + } else { + data_len.wrapping_sub(data_offset) + }; + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = if i as (usize) == n_objs.wrapping_sub(1usize) { + 0x82i32 + } else { + 0x83i32 + } as (u8); + offset = offset.wrapping_add( + _ykpiv_set_length( + buf.as_mut_ptr().offset(offset as (isize)), + data_chunk + ) as (usize) + ); + memcpy( + buf.as_mut_ptr().offset( + offset as (isize) + ) as (*mut ::std::os::raw::c_void), + data.offset( + data_offset as (isize) + ) as (*const ::std::os::raw::c_void), + data_chunk + ); + offset = offset.wrapping_add(data_chunk); + res = _ykpiv_save_object( + state, + 0x5fff11u32.wrapping_add(i) as (i32), + buf.as_mut_ptr(), + offset + ); + if Enum5::YKPIV_OK as (i32) != res as (i32) { + break; + } + data_offset = data_offset.wrapping_add(data_chunk); + i = i.wrapping_add(1u32); + } + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[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 ykpiv_util_generate_key( + mut state : *mut ykpiv_state, + mut slot : u8, + mut algorithm : u8, + mut pin_policy : u8, + mut touch_policy : u8, + mut modulus : *mut *mut u8, + mut modulus_len : *mut usize, + mut exp : *mut *mut u8, + mut exp_len : *mut usize, + mut point : *mut *mut u8, + mut point_len : *mut usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut in_data : [u8; 11]; + let mut in_ptr : *mut u8 = in_data.as_mut_ptr(); + let mut data : [u8; 1024]; + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut recv_len : usize = ::std::mem::size_of::<[u8; 1024]>(); + let mut sw : i32; + let mut ptr_modulus + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_modulus : usize = 0usize; + let mut ptr_exp + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_exp : usize = 0usize; + let mut ptr_point + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_point : usize = 0usize; + let mut setting_roca : _setting_bool_t; + let mut sz_setting_roca + : *const u8 + = (*b"Enable_Unsafe_Keygen_ROCA\0").as_ptr(); + let mut sz_roca_format + : *const u8 + = (*b"YubiKey serial number %u is affected by vulnerability CVE-2017-15361 (ROCA) and should be replaced. On-chip key generation %s See YSA-2017-01 for additional information on device replacement and mitigation assistance.\n\0").as_ptr( + ); + let mut sz_roca_allow_user + : *const u8 + = (*b"was permitted by an end-user configuration setting, but is not recommended.\0").as_ptr( + ); + let mut sz_roca_allow_admin + : *const u8 + = (*b"was permitted by an administrator configuration setting, but is not recommended.\0").as_ptr( + ); + let mut sz_roca_block_user + : *const u8 + = (*b"was blocked due to an end-user configuration setting.\0").as_ptr( + ); + let mut sz_roca_block_admin + : *const u8 + = (*b"was blocked due to an administrator configuration setting.\0").as_ptr( + ); + let mut sz_roca_default + : *const u8 + = (*b"was permitted by default, but is not recommended. The default behavior will change in a future Yubico release.\0").as_ptr( + ); + if state.is_null() { + Enum5::YKPIV_ARGUMENT_ERROR + } else { + if ykpiv_util_devicemodel( + state + ) == (0x594b0000i32 | 0x34i32) as (u32) && (algorithm as (i32) == 0x6i32 || algorithm as (i32) == 0x7i32) { + if (*state).ver.major as (i32) == 4i32 && ((*state).ver.minor as (i32) < 3i32 || (*state).ver.minor as (i32) == 3i32 && ((*state).ver.patch as (i32) < 5i32)) { + let mut psz_msg + : *const u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*const u8); + setting_roca = setting_get_bool(sz_setting_roca,true); + let switch9 = setting_roca.source; + if switch9 as (i32) == _setting_source_t::SETTING_SOURCE_USER as (i32) { + psz_msg = if setting_roca.value { + sz_roca_allow_user + } else { + sz_roca_block_user + }; + } else if switch9 as (i32) == _setting_source_t::SETTING_SOURCE_ADMIN as (i32) { + psz_msg = if setting_roca.value { + sz_roca_allow_admin + } else { + sz_roca_block_admin + }; + } else { + psz_msg = sz_roca_default; + } + fprintf(__stderrp,sz_roca_format,(*state).serial,psz_msg); + if !setting_roca.value { + return Enum5::YKPIV_NOT_SUPPORTED; + } + } + } + if algorithm as (i32) == 0x14i32 || algorithm as (i32) == 0x11i32 { + if point.is_null() || point_len.is_null() { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Invalid output parameter for ECC algorithm\0").as_ptr() + ); + } + return Enum5::YKPIV_GENERIC_ERROR; + } else { + *point = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *point_len = 0usize; + } + } else if algorithm as (i32) == 0x7i32 || algorithm as (i32) == 0x6i32 { + if modulus.is_null() || modulus_len.is_null() || exp.is_null( + ) || exp_len.is_null() { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Invalid output parameter for RSA algorithm\0").as_ptr() + ); + } + return Enum5::YKPIV_GENERIC_ERROR; + } else { + *modulus = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *modulus_len = 0usize; + *exp = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *exp_len = 0usize; + } + } else { + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Invalid algorithm specified\0").as_ptr()); + } + return Enum5::YKPIV_GENERIC_ERROR; + } + (if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + *templ.offset(3isize) = slot; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0xacu8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 3u8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0x80u8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 1u8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = algorithm; + if in_data[4usize] as (i32) == 0i32 { + res = Enum5::YKPIV_ALGORITHM_ERROR; + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Unexpected algorithm.\n\0").as_ptr()); + } + } else { + if pin_policy as (i32) != 0i32 { + let _rhs = 3i32; + let _lhs = &mut in_data[1usize]; + *_lhs = (*_lhs as (i32) + _rhs) as (u8); + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0xaau8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 1u8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = pin_policy; + } + if touch_policy as (i32) != 0i32 { + let _rhs = 3i32; + let _lhs = &mut in_data[1usize]; + *_lhs = (*_lhs as (i32) + _rhs) as (u8); + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0xabu8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 1u8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = touch_policy; + } + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_transfer_data( + state, + templ as (*const u8), + in_data.as_mut_ptr( + ) as (*const u8), + (in_ptr as (isize)).wrapping_sub( + in_data.as_mut_ptr( + ) as (isize) + ) / ::std::mem::size_of::( + ) as (isize), + data.as_mut_ptr(), + &mut recv_len as (*mut usize), + &mut sw as (*mut i32) + ); + res + } as (i32) { + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Failed to communicate.\n\0").as_ptr()); + } + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Failed to generate new key (\0").as_ptr()); + } + if sw == 0x6b00i32 { + res = Enum5::YKPIV_KEY_ERROR; + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"incorrect slot)\n\0").as_ptr()); + } + } else if sw == 0x6a80i32 { + res = Enum5::YKPIV_ALGORITHM_ERROR; + if (*state).verbose != 0 { + if pin_policy as (i32) != 0i32 { + fprintf( + __stderrp, + (*b"pin policy not supported?)\n\0").as_ptr() + ); + } else if touch_policy as (i32) != 0i32 { + fprintf( + __stderrp, + (*b"touch policy not supported?)\n\0").as_ptr() + ); + } else { + fprintf( + __stderrp, + (*b"algorithm not supported?)\n\0").as_ptr() + ); + } + } + } else if sw == 0x6982i32 { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"not authenticated)\n\0").as_ptr()); + } + } else { + res = Enum5::YKPIV_GENERIC_ERROR; + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"error %x)\n\0").as_ptr(),sw); + } + } + } else if 0x6i32 == algorithm as (i32) || 0x7i32 == algorithm as (i32) { + let mut data_ptr : *mut u8 = data.as_mut_ptr().offset(5isize); + let mut len : usize = 0usize; + if *data_ptr as (i32) != 0x81i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to parse public key structure (modulus).\n\0").as_ptr( + ) + ); + } + res = Enum5::YKPIV_PARSE_ERROR; + } else { + data_ptr = data_ptr.offset(1isize); + data_ptr = data_ptr.offset( + _ykpiv_get_length( + data_ptr as (*const u8), + &mut len as (*mut usize) + ) as (isize) + ); + cb_modulus = len; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == { + ptr_modulus = _ykpiv_alloc( + state, + cb_modulus + ) as (*mut u8); + ptr_modulus + } { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to allocate memory for modulus.\n\0").as_ptr() + ); + } + res = Enum5::YKPIV_MEMORY_ERROR; + } else { + memcpy( + ptr_modulus as (*mut ::std::os::raw::c_void), + data_ptr as (*const ::std::os::raw::c_void), + cb_modulus + ); + data_ptr = data_ptr.offset(len as (isize)); + if *data_ptr as (i32) != 0x82i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to parse public key structure (public exponent).\n\0").as_ptr( + ) + ); + } + res = Enum5::YKPIV_PARSE_ERROR; + } else { + data_ptr = data_ptr.offset(1isize); + data_ptr = data_ptr.offset( + _ykpiv_get_length( + data_ptr as (*const u8), + &mut len as (*mut usize) + ) as (isize) + ); + cb_exp = len; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == { + ptr_exp = _ykpiv_alloc( + state, + cb_exp + ) as (*mut u8); + ptr_exp + } { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to allocate memory for public exponent.\n\0").as_ptr( + ) + ); + } + res = Enum5::YKPIV_MEMORY_ERROR; + } else { + memcpy( + ptr_exp as (*mut ::std::os::raw::c_void), + data_ptr as (*const ::std::os::raw::c_void), + cb_exp + ); + *modulus = ptr_modulus; + ptr_modulus = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *modulus_len = cb_modulus; + *exp = ptr_exp; + ptr_exp = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *exp_len = cb_exp; + } + } + } + } + } else if 0x11i32 == algorithm as (i32) || 0x14i32 == algorithm as (i32) { + let mut data_ptr : *mut u8 = data.as_mut_ptr().offset(3isize); + let mut len : usize; + if 0x11i32 == algorithm as (i32) { + len = 65usize; + } else { + len = 97usize; + } + if *{ + let _old = data_ptr; + data_ptr = data_ptr.offset(1isize); + _old + } as (i32) != 0x86i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to parse public key structure.\n\0").as_ptr() + ); + } + res = Enum5::YKPIV_PARSE_ERROR; + } else if *{ + let _old = data_ptr; + data_ptr = data_ptr.offset(1isize); + _old + } as (usize) != len { + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Unexpected length.\n\0").as_ptr()); + } + res = Enum5::YKPIV_ALGORITHM_ERROR; + } else { + cb_point = len; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == { + ptr_point = _ykpiv_alloc( + state, + cb_point + ) as (*mut u8); + ptr_point + } { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to allocate memory for public point.\n\0").as_ptr( + ) + ); + } + res = Enum5::YKPIV_MEMORY_ERROR; + } else { + memcpy( + ptr_point as (*mut ::std::os::raw::c_void), + data_ptr as (*const ::std::os::raw::c_void), + cb_point + ); + *point = ptr_point; + ptr_point = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *point_len = cb_point; + } + } + } else { + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Wrong algorithm.\n\0").as_ptr()); + } + res = Enum5::YKPIV_ALGORITHM_ERROR; + } + } + } + if !ptr_modulus.is_null() { + _ykpiv_free(state,modulus as (*mut ::std::os::raw::c_void)); + } + if !ptr_exp.is_null() { + _ykpiv_free(state,ptr_exp as (*mut ::std::os::raw::c_void)); + } + if !ptr_point.is_null() { + _ykpiv_free(state,ptr_exp as (*mut ::std::os::raw::c_void)); + } + _ykpiv_end_transaction(state); + res + }) + } +} + +#[derive(Clone, Copy)] +#[repr(i32)] +pub enum Enum10 { + YKPIV_CONFIG_MGM_MANUAL = 0i32, + YKPIV_CONFIG_MGM_DERIVED = 1i32, + YKPIV_CONFIG_MGM_PROTECTED = 2i32, +} + +#[derive(Copy)] +#[repr(C)] +pub struct _ykpiv_config { + pub protected_data_available : u8, + pub puk_blocked : u8, + pub puk_noblock_on_upgrade : u8, + pub pin_last_changed : u32, + pub mgm_type : Enum10, +} + +impl Clone for _ykpiv_config { + fn clone(&self) -> Self { *self } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_get_config( + mut state : *mut ykpiv_state, mut config : *mut _ykpiv_config +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut data : [u8; 3072]; + let mut cb_data : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut p_item + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_item : usize = 0usize; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_config) == config { + Enum5::YKPIV_GENERIC_ERROR + } else { + (*config).protected_data_available = 0u8; + (*config).puk_blocked = 0u8; + (*config).puk_noblock_on_upgrade = 0u8; + (*config).pin_last_changed = 0u32; + (*config).mgm_type = Enum10::YKPIV_CONFIG_MGM_MANUAL; + (if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if Enum5::YKPIV_OK as (i32) == _read_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ) as (i32) { + if Enum5::YKPIV_OK as (i32) == _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x81u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ) as (i32) { + if *p_item as (i32) & 0x1i32 != 0 { + (*config).puk_blocked = 1u8; + } + if *p_item as (i32) & 0x2i32 != 0 { + (*config).mgm_type = Enum10::YKPIV_CONFIG_MGM_PROTECTED; + } + } + if Enum5::YKPIV_OK as (i32) == _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x82u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ) as (i32) { + if (*config).mgm_type as (i32) != Enum10::YKPIV_CONFIG_MGM_MANUAL as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"conflicting types of mgm key administration configured\n\0").as_ptr( + ) + ); + } + } else { + (*config).mgm_type = Enum10::YKPIV_CONFIG_MGM_DERIVED; + } + } + if Enum5::YKPIV_OK as (i32) == _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x83u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ) as (i32) { + if 4usize != cb_item { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"pin timestamp in admin metadata is an invalid size\0").as_ptr( + ) + ); + } + } else { + memcpy( + &mut (*config).pin_last_changed as (*mut u32) as (*mut ::std::os::raw::c_void), + p_item as (*const ::std::os::raw::c_void), + cb_item + ); + } + } + } + cb_data = ::std::mem::size_of::<[u8; 3072]>(); + if Enum5::YKPIV_OK as (i32) == _read_metadata( + state, + 0x88u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ) as (i32) { + (*config).protected_data_available = 1u8; + if Enum5::YKPIV_OK as (i32) == _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x81u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ) as (i32) { + if *p_item as (i32) & 0x1i32 != 0 { + (*config).puk_noblock_on_upgrade = 1u8; + } + } + if Enum5::YKPIV_OK as (i32) == _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x89u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ) as (i32) { + if (*config).mgm_type as (i32) != Enum10::YKPIV_CONFIG_MGM_PROTECTED as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"conflicting types of mgm key administration configured - protected mgm exists\n\0").as_ptr( + ) + ); + } + } + (*config).mgm_type = Enum10::YKPIV_CONFIG_MGM_PROTECTED; + } + } + } + _ykpiv_end_transaction(state); + res + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_set_pin_last_changed( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut ykrc : Enum5 = Enum5::YKPIV_OK; + let mut data : [u8; 3072]; + let mut cb_data : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut tnow : isize = 0isize; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if Enum5::YKPIV_OK as (i32) != { + ykrc = _read_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ); + ykrc + } as (i32) { + cb_data = 0usize; + } + tnow = time(0i32 as (*mut ::std::os::raw::c_void) as (*mut isize)); + if Enum5::YKPIV_OK as (i32) != { + res = _set_metadata_item( + data.as_mut_ptr(), + &mut cb_data as (*mut usize), + 3063usize, + 0x83u8, + &mut tnow as (*mut isize) as (*mut u8), + 4usize + ); + res + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not set pin timestamp, err = %d\n\0").as_ptr(), + res as (i32) + ); + } + } else if Enum5::YKPIV_OK as (i32) != { + res = _write_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + cb_data + ); + res + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not write admin data, err = %d\n\0").as_ptr(), + res as (i32) + ); + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[derive(Copy)] +#[repr(C)] +pub struct _ykpiv_mgm { + pub data : [u8; 24], +} + +impl Clone for _ykpiv_mgm { + fn clone(&self) -> Self { *self } +} + +#[derive(Clone, Copy)] +#[repr(i32)] +pub enum Enum11 { + PKCS5_OK = 0i32, + PKCS5_GENERAL_ERROR = -1i32, +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_get_derived_mgm( + mut state : *mut ykpiv_state, + mut pin : *const u8, + pin_len : usize, + mut mgm : *mut _ykpiv_mgm +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut p5rc : Enum11 = Enum11::PKCS5_OK; + let mut data : [u8; 3072]; + let mut cb_data : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut p_item + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_item : usize = 0usize; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) == pin || 0usize == pin_len || 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_mgm) == mgm { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if Enum5::YKPIV_OK as (i32) == { + res = _read_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ); + res + } as (i32) { + if Enum5::YKPIV_OK as (i32) == { + res = _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x82u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ); + res + } as (i32) { + if cb_item != 16usize { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"derived mgm salt exists, but is incorrect size = %lu\n\0").as_ptr( + ), + cb_item + ); + } + res = Enum5::YKPIV_GENERIC_ERROR; + } else if Enum11::PKCS5_OK as (i32) != { + p5rc = pkcs5_pbkdf2_sha1( + pin, + pin_len, + p_item as (*const u8), + cb_item, + 10000usize, + (*mgm).data.as_mut_ptr( + ) as (*const u8), + ::std::mem::size_of::<[u8; 24]>( + ) + ); + p5rc + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"pbkdf2 failure, err = %d\n\0").as_ptr(), + p5rc as (i32) + ); + } + res = Enum5::YKPIV_GENERIC_ERROR; + } + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_get_protected_mgm( + mut state : *mut ykpiv_state, mut mgm : *mut _ykpiv_mgm +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut data : [u8; 3072]; + let mut cb_data : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut p_item + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_item : usize = 0usize; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_mgm) == mgm { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if Enum5::YKPIV_OK as (i32) != { + res = _read_metadata( + state, + 0x88u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ); + res + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not read protected data, err = %d\n\0").as_ptr(), + res as (i32) + ); + } + } else if Enum5::YKPIV_OK as (i32) != { + res = _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x89u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ); + res + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not read protected mgm from metadata, err = %d\n\0").as_ptr( + ), + res as (i32) + ); + } + } else if cb_item != ::std::mem::size_of::<[u8; 24]>() { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"protected data contains mgm, but is the wrong size = %lu\n\0").as_ptr( + ), + cb_item + ); + } + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } else { + memcpy( + (*mgm).data.as_mut_ptr() as (*mut ::std::os::raw::c_void), + p_item as (*const ::std::os::raw::c_void), + cb_item + ); + } + } + memset_s( + data.as_mut_ptr() as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 3072]>(), + 0i32, + ::std::mem::size_of::<[u8; 3072]>() + ); + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_set_protected_mgm( + mut state : *mut ykpiv_state, mut mgm : *mut _ykpiv_mgm +) -> Enum5 { + let mut _currentBlock; + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut ykrc : Enum5 = Enum5::YKPIV_OK; + let mut prngrc : Enum7 = Enum7::PRNG_OK; + let mut fGenerate : bool = false; + let mut mgm_key : [u8; 24]; + let mut i : usize = 0usize; + let mut data : [u8; 3072]; + let mut cb_data : usize = ::std::mem::size_of::<[u8; 3072]>(); + let mut p_item + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_item : usize = 0usize; + let mut flags_1 : u8 = 0u8; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else { + if mgm.is_null() { + fGenerate = true; + } else { + fGenerate = true; + memcpy( + mgm_key.as_mut_ptr() as (*mut ::std::os::raw::c_void), + (*mgm).data.as_mut_ptr() as (*const ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 24]>() + ); + i = 0usize; + 'loop3: loop { + if !(i < ::std::mem::size_of::<[u8; 24]>()) { + _currentBlock = 8; + break; + } + if mgm_key[i] as (i32) != 0i32 { + _currentBlock = 6; + break; + } + i = i.wrapping_add(1usize); + } + if _currentBlock == 8 { + } else { + fGenerate = false; + } + } + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + res = Enum5::YKPIV_PCSC_ERROR; + } else if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + 'loop10: loop { + if fGenerate { + if Enum7::PRNG_OK as (i32) != { + prngrc = _ykpiv_prng_generate( + mgm_key.as_mut_ptr(), + ::std::mem::size_of::<[u8; 24]>() + ); + prngrc + } as (i32) { + _currentBlock = 47; + break; + } + } + if Enum5::YKPIV_OK as (i32) != { + ykrc = ykpiv_set_mgmkey( + state, + mgm_key.as_mut_ptr() as (*const u8) + ); + ykrc + } as (i32) { + if Enum5::YKPIV_KEY_ERROR as (i32) != ykrc as (i32) { + _currentBlock = 44; + break; + } + } else { + fGenerate = false; + } + if !fGenerate { + _currentBlock = 16; + break; + } + } + if _currentBlock == 16 { + if !mgm.is_null() { + memcpy( + (*mgm).data.as_mut_ptr() as (*mut ::std::os::raw::c_void), + mgm_key.as_mut_ptr() as (*const ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 24]>() + ); + } + if Enum5::YKPIV_OK as (i32) != { + ykrc = _read_metadata( + state, + 0x88u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ); + ykrc + } as (i32) { + cb_data = 0usize; + } + if Enum5::YKPIV_OK as (i32) != { + ykrc = _set_metadata_item( + data.as_mut_ptr(), + &mut cb_data as (*mut usize), + 3063usize, + 0x89u8, + mgm_key.as_mut_ptr(), + ::std::mem::size_of::<[u8; 24]>() + ); + ykrc + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not set protected mgm item, err = %d\n\0").as_ptr(), + ykrc as (i32) + ); + _currentBlock = 26; + } else { + _currentBlock = 26; + } + } else if Enum5::YKPIV_OK as (i32) != { + ykrc = _write_metadata( + state, + 0x88u8, + data.as_mut_ptr(), + cb_data + ); + ykrc + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not write protected data, err = %d\n\0").as_ptr(), + ykrc as (i32) + ); + _currentBlock = 51; + } else { + _currentBlock = 51; + } + } else { + _currentBlock = 26; + } + if _currentBlock == 51 { + } else { + cb_data = ::std::mem::size_of::<[u8; 3072]>(); + if Enum5::YKPIV_OK as (i32) != { + ykrc = _read_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + &mut cb_data as (*mut usize) + ); + ykrc + } as (i32) { + cb_data = 0usize; + } else { + if Enum5::YKPIV_OK as (i32) != { + ykrc = _get_metadata_item( + data.as_mut_ptr(), + cb_data, + 0x81u8, + &mut p_item as (*mut *mut u8), + &mut cb_item as (*mut usize) + ); + ykrc + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"admin data exists, but flags are not present\n\0").as_ptr() + ); + } + } + if cb_item == ::std::mem::size_of::() { + memcpy( + &mut flags_1 as (*mut u8) as (*mut ::std::os::raw::c_void), + p_item as (*const ::std::os::raw::c_void), + cb_item + ); + } else if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"admin data flags are an incorrect size = %lu\n\0").as_ptr(), + cb_item + ); + } + if Enum5::YKPIV_OK as (i32) != { + ykrc = _set_metadata_item( + data.as_mut_ptr(), + &mut cb_data as (*mut usize), + 3063usize, + 0x82u8, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + 0usize + ); + ykrc + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not unset derived mgm salt, err = %d\n\0").as_ptr(), + ykrc as (i32) + ); + } + } + } + flags_1 = (flags_1 as (i32) | 0x2i32) as (u8); + if Enum5::YKPIV_OK as (i32) != { + ykrc = _set_metadata_item( + data.as_mut_ptr(), + &mut cb_data as (*mut usize), + 3063usize, + 0x81u8, + &mut flags_1 as (*mut u8), + ::std::mem::size_of::() + ); + ykrc + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not set admin flags item, err = %d\n\0").as_ptr(), + ykrc as (i32) + ); + } + } else if Enum5::YKPIV_OK as (i32) != { + ykrc = _write_metadata( + state, + 0x80u8, + data.as_mut_ptr(), + cb_data + ); + ykrc + } as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not write admin data, err = %d\n\0").as_ptr(), + ykrc as (i32) + ); + } + } + } + } else if _currentBlock == 44 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not set new derived mgm key, err = %d\n\0").as_ptr(), + ykrc as (i32) + ); + } + res = ykrc; + } else { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"could not generate new mgm, err = %d\n\0").as_ptr(), + prngrc as (i32) + ); + } + res = Enum5::YKPIV_RANDOMNESS_ERROR; + } + } + memset_s( + data.as_mut_ptr() as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 3072]>(), + 0i32, + ::std::mem::size_of::<[u8; 3072]>() + ); + memset_s( + mgm_key.as_mut_ptr() as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 24]>(), + 0i32, + ::std::mem::size_of::<[u8; 24]>() + ); + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_reset( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut data : [u8; 255]; + let mut recv_len : usize = ::std::mem::size_of::<[u8; 255]>(); + let mut res : Enum5; + let mut sw : i32; + res = ykpiv_transfer_data( + state, + templ as (*const u8), + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8), + 0isize, + data.as_mut_ptr(), + &mut recv_len as (*mut usize), + &mut sw as (*mut i32) + ); + if Enum5::YKPIV_OK as (i32) == res as (i32) && (0x9000i32 == sw) { + Enum5::YKPIV_OK + } else { + Enum5::YKPIV_GENERIC_ERROR + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_util_slot_object(mut slot : u8) -> u32 { + let mut object_id : i32 = -1i32; + if slot as (i32) == 0xf9i32 { + object_id = 0x5fff01i32; + } else if slot as (i32) == 0x9ei32 { + object_id = 0x5fc101i32; + } else if slot as (i32) == 0x9di32 { + object_id = 0x5fc10bi32; + } else if slot as (i32) == 0x9ci32 { + object_id = 0x5fc10ai32; + } else if slot as (i32) == 0x9ai32 { + object_id = 0x5fc105i32; + } else if slot as (i32) >= 0x82i32 && (slot as (i32) <= 0x95i32) { + object_id = 0x5fc10di32 + (slot as (i32) - 0x82i32); + } + object_id as (u32) +} + +unsafe extern fn _read_certificate( + mut state : *mut ykpiv_state, + mut slot : u8, + mut buf : *mut u8, + mut buf_len : *mut usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut ptr + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut object_id : i32 = ykpiv_util_slot_object(slot) as (i32); + let mut len : usize = 0usize; + if -1i32 == object_id { + Enum5::YKPIV_INVALID_OBJECT + } else { + if Enum5::YKPIV_OK as (i32) == { + res = _ykpiv_fetch_object(state,object_id,buf,buf_len); + res + } as (i32) { + ptr = buf; + if *buf_len < 2usize { + *buf_len = 0usize; + return Enum5::YKPIV_OK; + } else if *{ + let _old = ptr; + ptr = ptr.offset(1isize); + _old + } as (i32) == 0x70i32 { + ptr = ptr.offset( + _ykpiv_get_length( + ptr as (*const u8), + &mut len as (*mut usize) + ) as (isize) + ); + if len > (*buf_len).wrapping_sub( + ((ptr as (isize)).wrapping_sub( + buf as (isize) + ) / ::std::mem::size_of::() as (isize)) as (usize) + ) { + *buf_len = 0usize; + return Enum5::YKPIV_OK; + } else { + memmove( + buf as (*mut ::std::os::raw::c_void), + ptr as (*const ::std::os::raw::c_void), + len + ); + *buf_len = len; + } + } + } else { + *buf_len = 0usize; + } + res + } +} + +unsafe extern fn _write_certificate( + mut state : *mut ykpiv_state, + mut slot : u8, + mut data : *mut u8, + mut data_len : usize, + mut certinfo : u8 +) -> Enum5 { + let mut buf : [u8; 3063]; + let mut object_id : i32 = ykpiv_util_slot_object(slot) as (i32); + let mut offset : usize = 0usize; + let mut req_len : usize = 0usize; + if -1i32 == object_id { + Enum5::YKPIV_INVALID_OBJECT + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == data || 0usize == data_len { + (if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) != data || 0usize != data_len { + Enum5::YKPIV_GENERIC_ERROR + } else { + _ykpiv_save_object( + state, + object_id, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + 0usize + ) + }) + } else { + req_len = (1i32 + 3i32 + 2i32) as (usize); + req_len = req_len.wrapping_add( + _ykpiv_set_length(buf.as_mut_ptr(),data_len) as (usize) + ); + req_len = req_len.wrapping_add(data_len); + (if req_len < data_len { + Enum5::YKPIV_SIZE_ERROR + } else if req_len > _obj_size_max(state) { + Enum5::YKPIV_SIZE_ERROR + } else { + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = 0x70u8; + offset = offset.wrapping_add( + _ykpiv_set_length( + buf.as_mut_ptr().offset(offset as (isize)), + data_len + ) as (usize) + ); + memcpy( + buf.as_mut_ptr().offset( + offset as (isize) + ) as (*mut ::std::os::raw::c_void), + data as (*const ::std::os::raw::c_void), + data_len + ); + offset = offset.wrapping_add(data_len); + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = 0x71u8; + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = 0x1u8; + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = if certinfo as (i32) == 1i32 { + 0x1i32 + } else { + 0x0i32 + } as (u8); + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = 0xfeu8; + buf[ + { + let _old = offset; + offset = offset.wrapping_add(1usize); + _old + } + ] = 0o0u8; + _ykpiv_save_object(state,object_id,buf.as_mut_ptr(),offset) + }) + } +} + +unsafe extern fn _get_metadata_item( + mut data : *mut u8, + mut cb_data : usize, + mut tag : u8, + mut pp_item : *mut *mut u8, + mut pcb_item : *mut usize +) -> Enum5 { + let mut _currentBlock; + let mut p_temp : *mut u8 = data; + let mut cb_temp : usize = 0usize; + let mut tag_temp : u8 = 0u8; + if data.is_null() || pp_item.is_null() || pcb_item.is_null() { + Enum5::YKPIV_GENERIC_ERROR + } else { + *pp_item = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + *pcb_item = 0usize; + 'loop2: loop { + if !(p_temp < data.offset(cb_data as (isize))) { + _currentBlock = 6; + break; + } + tag_temp = *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + }; + if !_ykpiv_has_valid_length( + p_temp as (*const u8), + ((data.offset(cb_data as (isize)) as (isize)).wrapping_sub( + p_temp as (isize) + ) / ::std::mem::size_of::() as (isize)) as (usize) + ) { + _currentBlock = 9; + break; + } + p_temp = p_temp.offset( + _ykpiv_get_length( + p_temp as (*const u8), + &mut cb_temp as (*mut usize) + ) as (isize) + ); + if tag_temp as (i32) == tag as (i32) { + _currentBlock = 6; + break; + } + p_temp = p_temp.offset(cb_temp as (isize)); + } + (if _currentBlock == 6 { + (if p_temp < data.offset(cb_data as (isize)) { + *pp_item = p_temp; + *pcb_item = cb_temp; + Enum5::YKPIV_OK + } else { + Enum5::YKPIV_GENERIC_ERROR + }) + } else { + Enum5::YKPIV_SIZE_ERROR + }) + } +} + +unsafe extern fn _get_length_size(mut length : usize) -> i32 { + if length < 0x80usize { + 1i32 + } else if length < 0xffusize { + 2i32 + } else { + 3i32 + } +} + +unsafe extern fn _set_metadata_item( + mut data : *mut u8, + mut pcb_data : *mut usize, + mut cb_data_max : usize, + mut tag : u8, + mut p_item : *mut u8, + mut cb_item : usize +) -> Enum5 { + let mut _currentBlock; + let mut p_temp : *mut u8 = data; + let mut cb_temp : usize = 0usize; + let mut tag_temp : u8 = 0u8; + let mut cb_len : usize = 0usize; + let mut p_next + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_moved : isize = 0isize; + if data.is_null() || pcb_data.is_null() { + Enum5::YKPIV_GENERIC_ERROR + } else { + 'loop1: loop { + if !(p_temp < data.offset(*pcb_data as (isize))) { + _currentBlock = 2; + break; + } + tag_temp = *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + }; + cb_len = _ykpiv_get_length( + p_temp as (*const u8), + &mut cb_temp as (*mut usize) + ) as (usize); + p_temp = p_temp.offset(cb_len as (isize)); + if tag_temp as (i32) == tag as (i32) { + _currentBlock = 9; + break; + } + p_temp = p_temp.offset(cb_temp as (isize)); + } + (if _currentBlock == 2 { + (if cb_item == 0usize { + Enum5::YKPIV_OK + } else { + p_temp = data.offset(*pcb_data as (isize)); + cb_len = _get_length_size(cb_item) as (usize); + (if (*pcb_data).wrapping_add(cb_len).wrapping_add( + cb_item + ) > cb_data_max { + Enum5::YKPIV_GENERIC_ERROR + } else { + *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + } = tag; + p_temp = p_temp.offset( + _ykpiv_set_length(p_temp,cb_item) as (isize) + ); + memcpy( + p_temp as (*mut ::std::os::raw::c_void), + p_item as (*const ::std::os::raw::c_void), + cb_item + ); + *pcb_data = (*pcb_data).wrapping_add( + 1usize.wrapping_add(cb_len).wrapping_add(cb_item) + ); + Enum5::YKPIV_OK + }) + }) + } else if cb_temp == cb_item { + memcpy( + p_temp as (*mut ::std::os::raw::c_void), + p_item as (*const ::std::os::raw::c_void), + cb_item + ); + Enum5::YKPIV_OK + } else { + p_next = p_temp.offset(cb_temp as (isize)); + cb_moved = cb_item as (isize) - cb_temp as (isize) + (if cb_item != 0usize { + _get_length_size(cb_item) + } else { + -1i32 + } as (isize) - cb_len as (isize)); + (if (*pcb_data).wrapping_add(cb_moved as (usize)) > cb_data_max { + Enum5::YKPIV_GENERIC_ERROR + } else { + memmove( + p_next.offset(cb_moved) as (*mut ::std::os::raw::c_void), + p_next as (*const ::std::os::raw::c_void), + (*pcb_data).wrapping_sub( + ((p_next as (isize)).wrapping_sub( + data as (isize) + ) / ::std::mem::size_of::() as (isize)) as (usize) + ) + ); + *pcb_data = (*pcb_data).wrapping_add(cb_moved as (usize)); + if cb_item != 0usize { + p_temp = p_temp.offset(-(cb_len as (isize))); + p_temp = p_temp.offset( + _ykpiv_set_length(p_temp,cb_item) as (isize) + ); + memcpy( + p_temp as (*mut ::std::os::raw::c_void), + p_item as (*const ::std::os::raw::c_void), + cb_item + ); + } + Enum5::YKPIV_OK + }) + }) + } +} + +unsafe extern fn _read_metadata( + mut state : *mut ykpiv_state, + mut tag : u8, + mut data : *mut u8, + mut pcb_data : *mut usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut p_temp + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + let mut cb_temp : usize = 0usize; + let mut obj_id : i32 = 0i32; + if data.is_null() || pcb_data.is_null() || 3072usize > *pcb_data { + Enum5::YKPIV_GENERIC_ERROR + } else { + if tag as (i32) == 0x88i32 { + obj_id = 0x5fc109i32; + } else if tag as (i32) == 0x80i32 { + obj_id = 0x5fff00i32; + } else { + return Enum5::YKPIV_INVALID_OBJECT; + } + cb_temp = *pcb_data; + *pcb_data = 0usize; + (if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_fetch_object( + state, + obj_id, + data, + &mut cb_temp as (*mut usize) + ); + res + } as (i32) { + res + } else if cb_temp < 2usize { + Enum5::YKPIV_GENERIC_ERROR + } else { + p_temp = data; + (if tag as (i32) != *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + } as (i32) { + Enum5::YKPIV_GENERIC_ERROR + } else { + p_temp = p_temp.offset( + _ykpiv_get_length(p_temp as (*const u8),pcb_data) as (isize) + ); + (if *pcb_data > cb_temp.wrapping_sub( + ((p_temp as (isize)).wrapping_sub( + data as (isize) + ) / ::std::mem::size_of::() as (isize)) as (usize) + ) { + *pcb_data = 0usize; + Enum5::YKPIV_GENERIC_ERROR + } else { + memmove( + data as (*mut ::std::os::raw::c_void), + p_temp as (*const ::std::os::raw::c_void), + *pcb_data + ); + Enum5::YKPIV_OK + }) + }) + }) + } +} + +unsafe extern fn _write_metadata( + mut state : *mut ykpiv_state, + mut tag : u8, + mut data : *mut u8, + mut cb_data : usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut buf : [u8; 3063]; + let mut pTemp : *mut u8 = buf.as_mut_ptr(); + let mut obj_id : i32 = 0i32; + if cb_data > _obj_size_max(state).wrapping_sub( + (2i32 + 2i32) as (usize) + ) { + Enum5::YKPIV_GENERIC_ERROR + } else { + if tag as (i32) == 0x88i32 { + obj_id = 0x5fc109i32; + } else if tag as (i32) == 0x80i32 { + obj_id = 0x5fff00i32; + } else { + return Enum5::YKPIV_INVALID_OBJECT; + } + if data.is_null() || 0usize == cb_data { + res = _ykpiv_save_object( + state, + obj_id, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + 0usize + ); + } else { + *{ + let _old = pTemp; + pTemp = pTemp.offset(1isize); + _old + } = tag; + pTemp = pTemp.offset(_ykpiv_set_length(pTemp,cb_data) as (isize)); + memcpy( + pTemp as (*mut ::std::os::raw::c_void), + data as (*const ::std::os::raw::c_void), + cb_data + ); + pTemp = pTemp.offset(cb_data as (isize)); + res = _ykpiv_save_object( + state, + obj_id, + buf.as_mut_ptr(), + ((pTemp as (isize)).wrapping_sub( + buf.as_mut_ptr() as (isize) + ) / ::std::mem::size_of::() as (isize)) as (usize) + ); + } + res + } +} diff --git a/lib/version.rs b/lib/version.rs new file mode 100644 index 0000000..368395d --- /dev/null +++ b/lib/version.rs @@ -0,0 +1,169 @@ +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) + } +} diff --git a/lib/ykpiv-version.h b/lib/ykpiv-version.h new file mode 100644 index 0000000..64976d8 --- /dev/null +++ b/lib/ykpiv-version.h @@ -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 diff --git a/lib/ykpiv.c b/lib/ykpiv.c index c80df15..4ac6667 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -105,7 +105,7 @@ static ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len); static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool force); static ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_version); -static unsigned const char aid[] = { +static unsigned const char *aid = { 0xa0, 0x00, 0x00, 0x03, 0x08 }; @@ -277,11 +277,14 @@ ykpiv_rc _ykpiv_select_application(ykpiv_state *state) { int sw; ykpiv_rc res = YKPIV_OK; + /* XXX FIX THIS!!! */ +/* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; apdu.st.p1 = 0x04; apdu.st.lc = sizeof(aid); memcpy(apdu.st.data, aid, sizeof(aid)); +*/ if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { if(state->verbose) { @@ -591,6 +594,8 @@ ykpiv_rc _ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, uint32_t recv_len = sizeof(data); APDU apdu; + /* XXX FIX THIS!!! */ +/* memset(apdu.raw, 0, sizeof(apdu.raw)); memcpy(apdu.raw, templ, 4); if(in_ptr + 0xff < in_data + in_len) { @@ -598,11 +603,15 @@ ykpiv_rc _ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, } else { this_size = (size_t)((in_data + in_len) - in_ptr); } + */ if(state->verbose > 2) { fprintf(stderr, "Going to send %lu bytes in this go.\n", (unsigned long)this_size); } + /* XXX FIX THIS!!! */ + /* apdu.st.lc = (unsigned char)this_size; memcpy(apdu.st.data, in_ptr, this_size); + */ res = _send_data(state, &apdu, data, &recv_len, sw); if(res != YKPIV_OK) { goto Cleanup; @@ -632,8 +641,11 @@ ykpiv_rc _ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, fprintf(stderr, "The card indicates there is %d bytes more data for us.\n", *sw & 0xff); } + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu.raw)); apdu.st.ins = YKPIV_INS_GET_RESPONSE_APDU; + */ res = _send_data(state, &apdu, data, &recv_len, sw); if(res != YKPIV_OK) { goto Cleanup; @@ -674,14 +686,17 @@ ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, ykpiv_rc _send_data(ykpiv_state *state, APDU *apdu, unsigned char *data, uint32_t *recv_len, int *sw) { long rc; - unsigned int send_len = (unsigned int)apdu->st.lc + 5; + unsigned int send_len = 0; /* XXX FIX THIS!!! (unsigned int)apdu->st.lc + 5; */ pcsc_word tmp_len = *recv_len; + /* XXX FIX THIS!!! */ + /* if(state->verbose > 1) { fprintf(stderr, "> "); dump_hex(apdu->raw, send_len); fprintf(stderr, "\n"); } + rc = SCardTransmit(state->card, SCARD_PCI_T1, apdu->raw, send_len, NULL, data, &tmp_len); if(rc != SCARD_S_SUCCESS) { if(state->verbose) { @@ -689,6 +704,7 @@ ykpiv_rc _send_data(ykpiv_state *state, APDU *apdu, } return YKPIV_PCSC_ERROR; } + */ *recv_len = (uint32_t)tmp_len; if(state->verbose > 1) { @@ -732,11 +748,13 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) { } /* get a challenge from the card */ + /* XXX FIX THIS!!! */ + /* { memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_AUTHENTICATE; - apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */ - apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */ + apdu.st.p1 = YKPIV_ALGO_3DES; // triple des + apdu.st.p2 = YKPIV_KEY_CARDMGM; // management key apdu.st.lc = 0x04; apdu.st.data[0] = 0x7c; apdu.st.data[1] = 0x02; @@ -749,9 +767,11 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) { goto Cleanup; } memcpy(challenge, data + 4, 8); - } + }*/ /* send a response to the cards challenge and a challenge of our own. */ + /* XXX FIX THIS!!! */ + /* { unsigned char *dataptr = apdu.st.data; unsigned char response[8]; @@ -766,10 +786,10 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) { recv_len = sizeof(data); memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_AUTHENTICATE; - apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */ - apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */ + apdu.st.p1 = YKPIV_ALGO_3DES; // triple des + apdu.st.p2 = YKPIV_KEY_CARDMGM; // management key *dataptr++ = 0x7c; - *dataptr++ = 20; /* 2 + 8 + 2 +8 */ + *dataptr++ = 20; // 2 + 8 + 2 +8 *dataptr++ = 0x80; *dataptr++ = 8; memcpy(dataptr, response, 8); @@ -794,6 +814,7 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) { goto Cleanup; } } + */ /* compare the response from the card with our challenge */ { @@ -848,6 +869,8 @@ ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, con goto Cleanup; } + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_SET_MGMKEY; apdu.st.p1 = 0xff; @@ -867,6 +890,7 @@ ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, con apdu.st.data[1] = YKPIV_KEY_CARDMGM; apdu.st.data[2] = DES_LEN_3DES; memcpy(apdu.st.data + 3, new_key, DES_LEN_3DES); + */ if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { goto Cleanup; @@ -882,7 +906,7 @@ Cleanup: return res; } -static char hex_translate[] = "0123456789abcdef"; +static char *hex_translate = "0123456789abcdef"; ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, unsigned char *hex_out, size_t *out_len) { @@ -920,7 +944,7 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, unsigned char indata[1024]; unsigned char *dataptr = indata; unsigned char data[1024]; - unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key}; + unsigned char *templ = {0, YKPIV_INS_AUTHENTICATE, algorithm, key}; unsigned long recv_len = sizeof(data); size_t key_len = 0; int sw = 0; @@ -1078,9 +1102,11 @@ static ykpiv_rc _ykpiv_get_version(ykpiv_state *state, ykpiv_version_t *p_versio } /* get version from device */ - + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_GET_VERSION; + */ if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { return res; } else if(sw == SW_SUCCESS) { @@ -1128,7 +1154,7 @@ Cleanup: static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f_force) { ykpiv_rc res = YKPIV_OK; APDU apdu; - const uint8_t yk_applet[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01 }; + const uint8_t *yk_applet = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01 }; unsigned char data[0xff]; uint32_t recv_len = sizeof(data); int sw; @@ -1148,11 +1174,12 @@ static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f uint8_t temp[0xff]; recv_len = sizeof(temp); - memset(apdu.raw, 0, sizeof(apdu)); + /* XXX FIX THIS!!! */ + /*memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; apdu.st.p1 = 0x04; apdu.st.lc = sizeof(yk_applet); - memcpy(apdu.st.data, yk_applet, sizeof(yk_applet)); + memcpy(apdu.st.data, yk_applet, sizeof(yk_applet));*/ if ((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) { if (state->verbose) { @@ -1169,10 +1196,13 @@ static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f } recv_len = sizeof(data); + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = 0x01; apdu.st.p1 = 0x10; apdu.st.lc = 0x00; + */ if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) { if (state->verbose) { @@ -1189,11 +1219,14 @@ static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f } recv_len = sizeof(temp); + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; apdu.st.p1 = 0x04; apdu.st.lc = (unsigned char)sizeof(aid); memcpy(apdu.st.data, aid, sizeof(aid)); + */ if((res = _send_data(state, &apdu, temp, &recv_len, &sw)) < YKPIV_OK) { if(state->verbose) { @@ -1211,8 +1244,9 @@ static ykpiv_rc _ykpiv_get_serial(ykpiv_state *state, uint32_t *p_serial, bool f else { /* get serial from yk5 and later devices using the f8 command */ - memset(apdu.raw, 0, sizeof(apdu)); - apdu.st.ins = YKPIV_INS_GET_SERIAL; + /* XXX FIX THIS!!! */ + /*memset(apdu.raw, 0, sizeof(apdu)); + apdu.st.ins = YKPIV_INS_GET_SERIAL;*/ if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { if(state->verbose) { @@ -1300,6 +1334,8 @@ static ykpiv_rc _verify(ykpiv_state *state, const char *pin, const size_t pin_le return YKPIV_SIZE_ERROR; } + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu.raw)); apdu.st.ins = YKPIV_INS_VERIFY; apdu.st.p1 = 0x00; @@ -1310,7 +1346,7 @@ static ykpiv_rc _verify(ykpiv_state *state, const char *pin, const size_t pin_le if (pin_len < CB_PIN_MAX) { memset(apdu.st.data + pin_len, 0xff, CB_PIN_MAX - pin_len); } - } + }*/ res = _send_data(state, &apdu, data, &recv_len, &sw); yc_memzero(&apdu, sizeof(apdu)); @@ -1377,7 +1413,7 @@ ykpiv_rc ykpiv_get_pin_retries(ykpiv_state *state, int *tries) { ykpiv_rc ykpiv_set_pin_retries(ykpiv_state *state, int pin_tries, int puk_tries) { ykpiv_rc res = YKPIV_OK; - unsigned char templ[] = {0, YKPIV_INS_SET_PIN_RETRIES, 0, 0}; + unsigned char *templ = {0, YKPIV_INS_SET_PIN_RETRIES, 0, 0}; unsigned char data[0xff]; unsigned long recv_len = sizeof(data); int sw = 0; @@ -1417,7 +1453,7 @@ Cleanup: static ykpiv_rc _ykpiv_change_pin(ykpiv_state *state, int action, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) { int sw; - unsigned char templ[] = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80}; + unsigned char *templ = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80}; unsigned char indata[0x10]; unsigned char data[0xff]; unsigned long recv_len = sizeof(data); @@ -1527,7 +1563,7 @@ ykpiv_rc _ykpiv_fetch_object(ykpiv_state *state, int object_id, int sw; unsigned char indata[5]; unsigned char *inptr = indata; - unsigned char templ[] = {0, YKPIV_INS_GET_DATA, 0x3f, 0xff}; + unsigned char *templ = {0, YKPIV_INS_GET_DATA, 0x3f, 0xff}; ykpiv_rc res; inptr = set_object(object_id, inptr); @@ -1543,7 +1579,7 @@ ykpiv_rc _ykpiv_fetch_object(ykpiv_state *state, int object_id, if(sw == SW_SUCCESS) { size_t outlen = 0; unsigned int offs = 0; - + if ((*len < 2) || !_ykpiv_has_valid_length(data + 1, *len - 1)) { return YKPIV_SIZE_ERROR; } @@ -1587,7 +1623,7 @@ ykpiv_rc _ykpiv_save_object( size_t len) { unsigned char data[CB_BUF_MAX]; unsigned char *dataptr = data; - unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff}; + unsigned char *templ = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff}; int sw; ykpiv_rc res; unsigned long outlen = 0; @@ -1631,7 +1667,7 @@ ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, u unsigned char key_data[1024]; unsigned char *in_ptr = key_data; - unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key}; + unsigned char *templ = {0, YKPIV_INS_IMPORT_KEY, algorithm, key}; unsigned char data[256]; unsigned long recv_len = sizeof(data); unsigned elem_len; @@ -1771,7 +1807,7 @@ Cleanup: ykpiv_rc ykpiv_attest(ykpiv_state *state, const unsigned char key, unsigned char *data, size_t *data_len) { ykpiv_rc res; - unsigned char templ[] = {0, YKPIV_INS_ATTEST, key, 0}; + unsigned char *templ = {0, YKPIV_INS_ATTEST, key, 0}; int sw; unsigned long ul_data_len; @@ -1810,7 +1846,7 @@ Cleanup: ykpiv_rc ykpiv_auth_getchallenge(ykpiv_state *state, uint8_t *challenge, const size_t challenge_len) { ykpiv_rc res = YKPIV_OK; APDU apdu = { 0 }; - unsigned char data[261] = { 0 }; + unsigned char data[261]; /* XXX ZERO THIS!!! */ uint32_t recv_len = sizeof(data); int sw = 0; @@ -1822,14 +1858,17 @@ ykpiv_rc ykpiv_auth_getchallenge(ykpiv_state *state, uint8_t *challenge, const s if (YKPIV_OK != (res = _ykpiv_ensure_application_selected(state))) goto Cleanup; /* get a challenge from the card */ + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_AUTHENTICATE; - apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */ - apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */ + apdu.st.p1 = YKPIV_ALGO_3DES; // triple des + apdu.st.p2 = YKPIV_KEY_CARDMGM; // management key apdu.st.lc = 0x04; apdu.st.data[0] = 0x7c; apdu.st.data[1] = 0x02; apdu.st.data[2] = 0x81; //0x80; + */ if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { goto Cleanup; } @@ -1848,10 +1887,10 @@ Cleanup: ykpiv_rc ykpiv_auth_verifyresponse(ykpiv_state *state, uint8_t *response, const size_t response_len) { ykpiv_rc res = YKPIV_OK; APDU apdu = { 0 }; - unsigned char data[261] = { 0 }; + unsigned char data[261]; /* XXX ZERO THIS!!! */ uint32_t recv_len = sizeof(data); int sw = 0; - unsigned char *dataptr = apdu.st.data; + unsigned char *dataptr = 0; /* XXX FIX THIS!!! apdu.st.data; */ if (NULL == state) return YKPIV_GENERIC_ERROR; if (NULL == response) return YKPIV_GENERIC_ERROR; @@ -1862,17 +1901,21 @@ ykpiv_rc ykpiv_auth_verifyresponse(ykpiv_state *state, uint8_t *response, const /* send the response to the card and a challenge of our own. */ recv_len = sizeof(data); + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_AUTHENTICATE; - apdu.st.p1 = YKPIV_ALGO_3DES; /* triple des */ - apdu.st.p2 = YKPIV_KEY_CARDMGM; /* management key */ + apdu.st.p1 = YKPIV_ALGO_3DES; // triple des + apdu.st.p2 = YKPIV_KEY_CARDMGM; // management key + */ *dataptr++ = 0x7c; *dataptr++ = 0x0a; /* 2 + 8 */ *dataptr++ = 0x82; *dataptr++ = 8; memcpy(dataptr, response, response_len); dataptr += 8; - apdu.st.lc = (unsigned char)(dataptr - apdu.st.data); + /* XXX FIX THIS!!! */ + //apdu.st.lc = (unsigned char)(dataptr - apdu.st.data); if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { goto Cleanup; } @@ -1888,7 +1931,7 @@ Cleanup: return res; } -static const uint8_t MGMT_AID[] = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 }; +static const uint8_t *MGMT_AID = { 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 }; /* deauthenticates the user pin and mgm key */ ykpiv_rc ykpiv_auth_deauthenticate(ykpiv_state *state) { @@ -1905,11 +1948,14 @@ ykpiv_rc ykpiv_auth_deauthenticate(ykpiv_state *state) { /* this function does not use ykpiv_transfer_data because it selects a different app */ if ((res = _ykpiv_begin_transaction(state)) < YKPIV_OK) return res; + /* XXX FIX THIS!!! */ + /* memset(apdu.raw, 0, sizeof(apdu)); apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; apdu.st.p1 = 0x04; apdu.st.lc = sizeof(MGMT_AID); memcpy(apdu.st.data, MGMT_AID, sizeof(MGMT_AID)); + */ if ((res = _send_data(state, &apdu, data, &recv_len, &sw)) < YKPIV_OK) { if (state->verbose) { diff --git a/lib/ykpiv.rs b/lib/ykpiv.rs new file mode 100644 index 0000000..c46f25c --- /dev/null +++ b/lib/ykpiv.rs @@ -0,0 +1,3250 @@ +extern { + fn SCardBeginTransaction(hCard : i32) -> i32; + fn SCardConnect( + hContext : i32, + szReader : *const u8, + dwShareMode : u32, + dwPreferredProtocols : u32, + phCard : *mut i32, + pdwActiveProtocol : *mut u32 + ) -> i32; + fn SCardDisconnect(hCard : i32, dwDisposition : u32) -> i32; + fn SCardEndTransaction(hCard : i32, dwDisposition : u32) -> i32; + fn SCardEstablishContext( + dwScope : u32, + pvReserved1 : *const ::std::os::raw::c_void, + pvReserved2 : *const ::std::os::raw::c_void, + phContext : *mut i32 + ) -> i32; + fn SCardIsValidContext(hContext : i32) -> i32; + fn SCardListReaders( + hContext : i32, + mszGroups : *const u8, + mszReaders : *mut u8, + pcchReaders : *mut u32 + ) -> i32; + fn SCardReconnect( + hCard : i32, + dwShareMode : u32, + dwPreferredProtocols : u32, + dwInitialization : u32, + pdwActiveProtocol : *mut u32 + ) -> i32; + fn SCardReleaseContext(hContext : i32) -> i32; + fn SCardStatus( + hCard : i32, + mszReaderNames : *mut u8, + pcchReaderLen : *mut u32, + pdwState : *mut u32, + pdwProtocol : *mut u32, + pbAtr : *mut u8, + pcbAtrLen : *mut u32 + ) -> i32; + static mut _DefaultRuneLocale : Struct1; + fn __maskrune(arg1 : i32, arg2 : usize) -> i32; + static mut __stderrp : *mut __sFILE; + fn __swbuf(arg1 : i32, arg2 : *mut __sFILE) -> i32; + fn __tolower(arg1 : i32) -> i32; + fn __toupper(arg1 : i32) -> i32; + fn calloc( + __count : usize, __size : usize + ) -> *mut ::std::os::raw::c_void; + fn des_destroy_key(key : *mut des_key) -> Enum6; + fn des_encrypt( + key : *mut des_key, + in_ : *const u8, + inlen : usize, + out : *mut u8, + outlen : *mut usize + ) -> Enum6; + fn des_import_key( + type_ : i32, + keyraw : *const u8, + keyrawlen : usize, + key : *mut *mut des_key + ) -> Enum6; + fn fprintf(arg1 : *mut __sFILE, arg2 : *const u8, ...) -> i32; + fn free(arg1 : *mut ::std::os::raw::c_void); + fn memcmp( + __s1 : *const ::std::os::raw::c_void, + __s2 : *const ::std::os::raw::c_void, + __n : usize + ) -> i32; + 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 memmove( + __dst : *mut ::std::os::raw::c_void, + __src : *const ::std::os::raw::c_void, + __len : 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 memset_s( + __s : *mut ::std::os::raw::c_void, + __smax : usize, + __c : i32, + __n : usize + ) -> i32; + fn realloc( + __ptr : *mut ::std::os::raw::c_void, __size : usize + ) -> *mut ::std::os::raw::c_void; + fn snprintf( + __str : *mut u8, __size : usize, __format : *const u8, ... + ) -> i32; + fn strchr(__s : *const u8, __c : i32) -> *mut u8; + fn strlen(__s : *const u8) -> usize; + fn strncasecmp( + arg1 : *const u8, arg2 : *const u8, arg3 : usize + ) -> i32; + fn strnlen(__s1 : *const u8, __n : usize) -> usize; + fn yk_des_is_weak_key(key : *const u8, cb_key : usize) -> bool; + fn ykpiv_strerror(err : Enum5) -> *const u8; +} + +enum __sFILEX { +} + +enum des_key { +} + +enum u_APDU { +} + +#[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 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) +} + +static mut aid : *const u8 = 0xa0i32 as (*const u8); + +#[derive(Copy)] +#[repr(C)] +pub struct ykpiv_allocator { + pub pfn_alloc : unsafe extern fn(*mut ::std::os::raw::c_void, usize) -> *mut ::std::os::raw::c_void, + pub pfn_realloc : unsafe extern fn(*mut ::std::os::raw::c_void, *mut ::std::os::raw::c_void, usize) -> *mut ::std::os::raw::c_void, + pub pfn_free : unsafe extern fn(*mut ::std::os::raw::c_void, *mut ::std::os::raw::c_void), + pub alloc_data : *mut ::std::os::raw::c_void, +} + +impl Clone for ykpiv_allocator { + fn clone(&self) -> Self { *self } +} + +unsafe extern fn _default_alloc( + mut data : *mut ::std::os::raw::c_void, mut cb : usize +) -> *mut ::std::os::raw::c_void { + data; + calloc(cb,1usize) +} + +unsafe extern fn _default_realloc( + mut data : *mut ::std::os::raw::c_void, + mut p : *mut ::std::os::raw::c_void, + mut cb : usize +) -> *mut ::std::os::raw::c_void { + data; + realloc(p,cb) +} + +unsafe extern fn _default_free( + mut data : *mut ::std::os::raw::c_void, + mut p : *mut ::std::os::raw::c_void +) { + data; + free(p); +} + +#[no_mangle] +pub static mut _default_allocator + : ykpiv_allocator + = ykpiv_allocator { + pfn_alloc: _default_alloc, + pfn_realloc: _default_realloc, + pfn_free: _default_free, + alloc_data: 0i32 as (*mut ::std::os::raw::c_void) + }; + +#[derive(Copy)] +#[repr(C)] +pub struct _ykpiv_version_t { + pub major : u8, + pub minor : u8, + pub patch : u8, +} + +impl Clone for _ykpiv_version_t { + fn clone(&self) -> Self { *self } +} + +#[derive(Copy)] +#[repr(C)] +pub struct ykpiv_state { + pub context : i32, + pub card : i32, + pub verbose : i32, + pub pin : *mut u8, + pub allocator : ykpiv_allocator, + pub isNEO : bool, + pub ver : _ykpiv_version_t, + pub serial : u32, +} + +impl Clone for ykpiv_state { + fn clone(&self) -> Self { *self } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_alloc( + mut state : *mut ykpiv_state, mut size : usize +) -> *mut ::std::os::raw::c_void { + if state.is_null() || (*state).allocator.pfn_alloc == 0 { + 0i32 as (*mut ::std::os::raw::c_void) + } else { + ((*state).allocator.pfn_alloc)((*state).allocator.alloc_data,size) + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_realloc( + mut state : *mut ykpiv_state, + mut address : *mut ::std::os::raw::c_void, + mut size : usize +) -> *mut ::std::os::raw::c_void { + if state.is_null() || (*state).allocator.pfn_realloc == 0 { + 0i32 as (*mut ::std::os::raw::c_void) + } else { + ((*state).allocator.pfn_realloc)( + (*state).allocator.alloc_data, + address, + size + ) + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_free( + mut state : *mut ykpiv_state, + mut data : *mut ::std::os::raw::c_void +) { if data.is_null() || state.is_null( + ) || (*state).allocator.pfn_free == 0 { + } else { + ((*state).allocator.pfn_free)((*state).allocator.alloc_data,data); + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_set_length( + mut buffer : *mut u8, mut length : usize +) -> u32 { + if length < 0x80usize { + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = length as (u8); + 1u32 + } else if length < 0x100usize { + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = 0x81u8; + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = length as (u8); + 2u32 + } else { + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = 0x82u8; + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = (length >> 8i32 & 0xffusize) as (u8); + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = (length as (u8) as (i32) & 0xffi32) as (u8); + 3u32 + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_get_length( + mut buffer : *const u8, mut len : *mut usize +) -> u32 { + if *buffer.offset(0isize) as (i32) < 0x81i32 { + *len = *buffer.offset(0isize) as (usize); + 1u32 + } else if *buffer as (i32) & 0x7fi32 == 1i32 { + *len = *buffer.offset(1isize) as (usize); + 2u32 + } else if *buffer as (i32) & 0x7fi32 == 2i32 { + let mut tmp : usize = *buffer.offset(1isize) as (usize); + *len = (tmp << 8i32).wrapping_add( + *buffer.offset(2isize) as (usize) + ); + 3u32 + } else { + 0u32 + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_has_valid_length( + mut buffer : *const u8, mut len : usize +) -> bool { + if *buffer.offset(0isize) as (i32) < 0x81i32 && (len > 0usize) { + true + } else if *buffer as (i32) & 0x7fi32 == 1i32 && (len > 1usize) { + true + } else if *buffer as (i32) & 0x7fi32 == 2i32 && (len > 2usize) { + true + } else { + false + } +} + +#[derive(Clone, Copy)] +#[repr(i32)] +pub enum Enum5 { + 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, +} + +#[no_mangle] +pub unsafe extern fn ykpiv_init_with_allocator( + mut state : *mut *mut ykpiv_state, + mut verbose : i32, + mut allocator : *const ykpiv_allocator +) -> Enum5 { + let mut s : *mut ykpiv_state; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut *mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*const ykpiv_allocator) == allocator || (*allocator).pfn_alloc == 0 || (*allocator).pfn_realloc == 0 || (*allocator).pfn_free == 0 { + Enum5::YKPIV_MEMORY_ERROR + } else { + s = ((*allocator).pfn_alloc)( + (*allocator).alloc_data, + ::std::mem::size_of::() + ) as (*mut ykpiv_state); + (if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == s { + Enum5::YKPIV_MEMORY_ERROR + } else { + memset( + s as (*mut ::std::os::raw::c_void), + 0i32, + ::std::mem::size_of::() + ); + (*s).pin = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + (*s).allocator = *allocator; + (*s).verbose = verbose; + (*s).context = -1i32; + *state = s; + Enum5::YKPIV_OK + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_init( + mut state : *mut *mut ykpiv_state, mut verbose : i32 +) -> Enum5 { + ykpiv_init_with_allocator( + state, + verbose, + &mut _default_allocator as (*mut ykpiv_allocator) as (*const ykpiv_allocator) + ) +} + +unsafe extern fn _ykpiv_done( + mut state : *mut ykpiv_state, mut disconnect : bool +) -> Enum5 { + if disconnect { + ykpiv_disconnect(state); + } + _cache_pin( + state, + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8), + 0usize + ); + _ykpiv_free(state,state as (*mut ::std::os::raw::c_void)); + Enum5::YKPIV_OK +} + +#[no_mangle] +pub unsafe extern fn ykpiv_done_with_external_card( + mut state : *mut ykpiv_state +) -> Enum5 { + _ykpiv_done(state,false) +} + +#[no_mangle] +pub unsafe extern fn ykpiv_done( + mut state : *mut ykpiv_state +) -> Enum5 { + _ykpiv_done(state,true) +} + +#[no_mangle] +pub unsafe extern fn ykpiv_disconnect( + mut state : *mut ykpiv_state +) -> Enum5 { + if (*state).card != 0 { + SCardDisconnect((*state).card,0x1u32); + (*state).card = 0i32; + } + if SCardIsValidContext((*state).context) == 0x0i32 { + SCardReleaseContext((*state).context); + (*state).context = -1i32; + } + Enum5::YKPIV_OK +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_select_application( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut apdu : u_APDU; + let mut data : [u8; 255]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 255]>() as (u32); + let mut sw : i32; + let mut res : Enum5 = Enum5::YKPIV_OK; + if { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed communicating with card: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + } + res + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed selecting application: %04x\n\0").as_ptr(), + sw + ); + } + Enum5::YKPIV_GENERIC_ERROR + } else { + res = _ykpiv_get_version( + state, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut _ykpiv_version_t) + ); + if res as (i32) != Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to retrieve version: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + } + } + res = _ykpiv_get_serial( + state, + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u32), + false + ); + if res as (i32) != Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed to retrieve serial number: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + } + res = Enum5::YKPIV_OK; + } + res + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_ensure_application_selected( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + state; + res +} + +unsafe extern fn _ykpiv_connect( + mut state : *mut ykpiv_state, mut context : usize, mut card : usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if context != (*state).context as (usize) && (0x0i32 != SCardIsValidContext( + context as (i32) + )) { + Enum5::YKPIV_PCSC_ERROR + } else { + if card != (*state).card as (usize) { + let mut reader : [u8; 3072]; + let mut reader_len + : u32 + = ::std::mem::size_of::<[u8; 3072]>() as (u32); + let mut atr : [u8; 33]; + let mut atr_len : u32 = ::std::mem::size_of::<[u8; 33]>() as (u32); + if 0x0i32 != SCardStatus( + card as (i32), + reader.as_mut_ptr(), + &mut reader_len as (*mut u32), + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u32), + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u32), + atr.as_mut_ptr(), + &mut atr_len as (*mut u32) + ) { + return Enum5::YKPIV_PCSC_ERROR; + } else { + (*state).isNEO = ::std::mem::size_of::<[u8; 23]>().wrapping_sub( + 1usize + ) == atr_len as (usize) && (0i32 == memcmp( + (*b";\xFC\x13\0\0\x811\xFE\x15YubikeyNEOr3\xE1\0").as_ptr( + ) as (*const ::std::os::raw::c_void), + atr.as_mut_ptr( + ) as (*const ::std::os::raw::c_void), + atr_len as (usize) + )); + } + } + (*state).context = context as (i32); + (*state).card = card as (i32); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_connect_with_external_card( + mut state : *mut ykpiv_state, mut context : usize, mut card : usize +) -> Enum5 { + _ykpiv_connect(state,context,card) +} + +#[no_mangle] +pub unsafe extern fn ykpiv_connect( + mut state : *mut ykpiv_state, mut wanted : *const u8 +) -> Enum5 { + let mut _currentBlock; + let mut active_protocol : u32; + let mut reader_buf : [u8; 2048]; + let mut num_readers : usize = ::std::mem::size_of::<[u8; 2048]>(); + let mut rc : isize; + let mut reader_ptr : *mut u8; + let mut card : i32 = -1i32; + let mut ret + : Enum5 + = ykpiv_list_readers( + state, + reader_buf.as_mut_ptr(), + &mut num_readers as (*mut usize) + ); + if ret as (i32) != Enum5::YKPIV_OK as (i32) { + ret + } else { + reader_ptr = reader_buf.as_mut_ptr(); + 'loop2: loop { + if !(*reader_ptr as (i32) != b'\0' as (i32)) { + _currentBlock = 3; + break; + } + if !wanted.is_null() { + let mut ptr : *mut u8 = reader_ptr; + let mut found : bool = false; + 'loop10: loop { + if strlen(ptr as (*const u8)) < strlen(wanted) { + _currentBlock = 14; + break; + } + if strncasecmp(ptr as (*const u8),wanted,strlen(wanted)) == 0i32 { + _currentBlock = 13; + break; + } + if *{ + let _old = ptr; + ptr = ptr.offset(1isize); + _old + } == 0 { + _currentBlock = 14; + break; + } + } + if _currentBlock == 13 { + found = true; + } + if found as (i32) == 0i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"skipping reader \'%s\' since it doesn\'t match \'%s\'.\n\0").as_ptr( + ), + reader_ptr, + wanted + ); + _currentBlock = 26; + } else { + _currentBlock = 26; + } + } else { + _currentBlock = 15; + } + } else { + _currentBlock = 15; + } + if _currentBlock == 15 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"trying to connect to reader \'%s\'.\n\0").as_ptr(), + reader_ptr + ); + } + rc = SCardConnect( + (*state).context, + reader_ptr as (*const u8), + 0x2u32, + 0x2u32, + &mut card as (*mut i32), + &mut active_protocol as (*mut u32) + ) as (isize); + if rc != 0x0isize { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"SCardConnect failed, rc=%08lx\n\0").as_ptr(), + rc + ); + } + } else if Enum5::YKPIV_OK as (i32) == _ykpiv_connect( + state, + (*state).context as (usize), + card as (usize) + ) as (i32) { + _currentBlock = 19; + break; + } + } + reader_ptr = reader_ptr.offset( + strlen(reader_ptr as (*const u8)).wrapping_add(1usize) as (isize) + ); + } + (if _currentBlock == 3 { + (if *reader_ptr as (i32) == b'\0' as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"error: no usable reader found.\n\0").as_ptr() + ); + } + SCardReleaseContext((*state).context); + (*state).context = -1i32; + Enum5::YKPIV_PCSC_ERROR + } else { + Enum5::YKPIV_GENERIC_ERROR + }) + } else if Enum5::YKPIV_OK as (i32) != { + ret = _ykpiv_begin_transaction(state); + ret + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + ret = _ykpiv_select_application(state); + _ykpiv_end_transaction(state); + ret + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_list_readers( + mut state : *mut ykpiv_state, + mut readers : *mut u8, + mut len : *mut usize +) -> Enum5 { + let mut num_readers : u32 = 0u32; + let mut rc : isize; + if SCardIsValidContext((*state).context) != 0x0i32 { + rc = SCardEstablishContext( + 0x2u32, + 0i32 as (*mut ::std::os::raw::c_void) as (*const ::std::os::raw::c_void), + 0i32 as (*mut ::std::os::raw::c_void) as (*const ::std::os::raw::c_void), + &mut (*state).context as (*mut i32) + ) as (isize); + if rc != 0x0isize { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"error: SCardEstablishContext failed, rc=%08lx\n\0").as_ptr(), + rc + ); + } + return Enum5::YKPIV_PCSC_ERROR; + } + } + rc = SCardListReaders( + (*state).context, + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8), + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + &mut num_readers as (*mut u32) + ) as (isize); + if rc != 0x0isize { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"error: SCardListReaders failed, rc=%08lx\n\0").as_ptr(), + rc + ); + } + SCardReleaseContext((*state).context); + (*state).context = -1i32; + Enum5::YKPIV_PCSC_ERROR + } else { + if num_readers as (usize) > *len { + num_readers = *len as (u32); + } else if num_readers as (usize) < *len { + *len = num_readers as (usize); + } + rc = SCardListReaders( + (*state).context, + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8), + readers, + &mut num_readers as (*mut u32) + ) as (isize); + (if rc != 0x0isize { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"error: SCardListReaders failed, rc=%08lx\n\0").as_ptr(), + rc + ); + } + SCardReleaseContext((*state).context); + (*state).context = -1i32; + Enum5::YKPIV_PCSC_ERROR + } else { + *len = num_readers as (usize); + Enum5::YKPIV_OK + }) + } +} + +unsafe extern fn reconnect(mut state : *mut ykpiv_state) -> Enum5 { + let mut active_protocol : u32 = 0u32; + let mut rc : isize; + let mut res : Enum5; + let mut tries : i32; + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"trying to reconnect to current reader.\n\0").as_ptr() + ); + } + rc = SCardReconnect( + (*state).card, + 0x2u32, + 0x2u32, + 0x1u32, + &mut active_protocol as (*mut u32) + ) as (isize); + if rc != 0x0isize { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"SCardReconnect failed, rc=%08lx\n\0").as_ptr(), + rc + ); + } + Enum5::YKPIV_PCSC_ERROR + } else if { + res = _ykpiv_select_application(state); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + res + } else if !(*state).pin.is_null() { + ykpiv_verify( + state, + (*state).pin as (*const u8), + &mut tries as (*mut i32) + ) + } else { + Enum5::YKPIV_OK + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_begin_transaction( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut rc : isize; + rc = SCardBeginTransaction((*state).card) as (isize); + if (rc as (usize) & 0xffffffffusize) as (isize) as (usize) == 0x80100068usize { + let mut res : Enum5 = Enum5::YKPIV_OK; + if { + res = reconnect(state); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + return res; + } else { + rc = SCardBeginTransaction((*state).card) as (isize); + } + } + if rc != 0x0isize { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"error: Failed to begin pcsc transaction, rc=%08lx\n\0").as_ptr( + ), + rc + ); + } + Enum5::YKPIV_PCSC_ERROR + } else { + Enum5::YKPIV_OK + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_end_transaction( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut rc + : isize + = SCardEndTransaction((*state).card,0x0u32) as (isize); + if rc != 0x0isize && ((*state).verbose != 0) { + fprintf( + __stderrp, + (*b"error: Failed to end pcsc transaction, rc=%08lx\n\0").as_ptr(), + rc + ); + Enum5::YKPIV_PCSC_ERROR + } else { + Enum5::YKPIV_OK + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_transfer_data( + mut state : *mut ykpiv_state, + mut templ : *const u8, + mut in_data : *const u8, + mut in_len : isize, + mut out_data : *mut u8, + mut out_len : *mut usize, + mut sw : *mut i32 +) -> Enum5 { + let mut _currentBlock; + let mut in_ptr : *const u8 = in_data; + let mut max_out : usize = *out_len; + let mut res : Enum5; + *out_len = 0usize; + 'loop1: loop { + let mut this_size : usize = 0xffusize; + let mut data : [u8; 261]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + let mut apdu : u_APDU; + if (*state).verbose > 2i32 { + fprintf( + __stderrp, + (*b"Going to send %lu bytes in this go.\n\0").as_ptr(), + this_size + ); + } + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + sw + ); + if res as (i32) != Enum5::YKPIV_OK as (i32) { + _currentBlock = 24; + break; + } + if *sw != 0x9000i32 && (*sw >> 8i32 != 0x61i32) { + _currentBlock = 24; + break; + } + if (*out_len).wrapping_add(recv_len as (usize)).wrapping_sub( + 2usize + ) > max_out { + _currentBlock = 21; + break; + } + if !out_data.is_null() { + memcpy( + out_data as (*mut ::std::os::raw::c_void), + data.as_mut_ptr() as (*const ::std::os::raw::c_void), + recv_len.wrapping_sub(2u32) as (usize) + ); + out_data = out_data.offset(recv_len.wrapping_sub(2u32) as (isize)); + *out_len = (*out_len).wrapping_add( + recv_len.wrapping_sub(2u32) as (usize) + ); + } + in_ptr = in_ptr.offset(this_size as (isize)); + if !(in_ptr < in_data.offset(in_len)) { + _currentBlock = 10; + break; + } + } + if _currentBlock == 10 { + 'loop10: loop { + if !(*sw >> 8i32 == 0x61i32) { + _currentBlock = 24; + break; + } + let mut apdu : u_APDU; + let mut data : [u8; 261]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + if (*state).verbose > 2i32 { + fprintf( + __stderrp, + (*b"The card indicates there is %d bytes more data for us.\n\0").as_ptr( + ), + *sw & 0xffi32 + ); + } + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + sw + ); + if res as (i32) != Enum5::YKPIV_OK as (i32) { + _currentBlock = 24; + break; + } + if *sw != 0x9000i32 && (*sw >> 8i32 != 0x61i32) { + _currentBlock = 24; + break; + } + if (*out_len).wrapping_add(recv_len as (usize)).wrapping_sub( + 2usize + ) > max_out { + _currentBlock = 18; + break; + } + if out_data.is_null() { + continue; + } + memcpy( + out_data as (*mut ::std::os::raw::c_void), + data.as_mut_ptr() as (*const ::std::os::raw::c_void), + recv_len.wrapping_sub(2u32) as (usize) + ); + out_data = out_data.offset(recv_len.wrapping_sub(2u32) as (isize)); + *out_len = (*out_len).wrapping_add( + recv_len.wrapping_sub(2u32) as (usize) + ); + } + if _currentBlock == 24 { + } else { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Output buffer to small, wanted to write %lu, max was %lu.\0").as_ptr( + ), + (*out_len).wrapping_add(recv_len as (usize)).wrapping_sub(2usize), + max_out + ); + } + res = Enum5::YKPIV_SIZE_ERROR; + } + } else if _currentBlock == 21 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Output buffer to small, wanted to write %lu, max was %lu.\n\0").as_ptr( + ), + (*out_len).wrapping_add(recv_len as (usize)).wrapping_sub(2usize), + max_out + ); + } + res = Enum5::YKPIV_SIZE_ERROR; + } + res +} + +#[no_mangle] +pub unsafe extern fn ykpiv_transfer_data( + mut state : *mut ykpiv_state, + mut templ : *const u8, + mut in_data : *const u8, + mut in_len : isize, + mut out_data : *mut u8, + mut out_len : *mut usize, + mut sw : *mut i32 +) -> Enum5 { + let mut res : Enum5; + if { + res = _ykpiv_begin_transaction(state); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + *out_len = 0usize; + Enum5::YKPIV_PCSC_ERROR + } else { + res = _ykpiv_transfer_data( + state, + templ, + in_data, + in_len, + out_data, + out_len, + sw + ); + _ykpiv_end_transaction(state); + res + } +} + +unsafe extern fn dump_hex(mut buf : *const u8, mut len : u32) { + let mut i : u32; + i = 0u32; + 'loop1: loop { + if !(i < len) { + break; + } + fprintf( + __stderrp, + (*b"%02x \0").as_ptr(), + *buf.offset(i as (isize)) as (i32) + ); + i = i.wrapping_add(1u32); + } +} + +#[no_mangle] +pub unsafe extern fn _send_data( + mut state : *mut ykpiv_state, + mut apdu : *mut u_APDU, + mut data : *mut u8, + mut recv_len : *mut u32, + mut sw : *mut i32 +) -> Enum5 { + let mut rc : isize; + let mut send_len : u32 = 0u32; + let mut tmp_len : u32 = *recv_len; + *recv_len = tmp_len; + if (*state).verbose > 1i32 { + fprintf(__stderrp,(*b"< \0").as_ptr()); + dump_hex(data as (*const u8),*recv_len); + fprintf(__stderrp,(*b"\n\0").as_ptr()); + } + if *recv_len >= 2u32 { + *sw = *data.offset( + (*recv_len).wrapping_sub(2u32) as (isize) + ) as (i32) << 8i32 | *data.offset( + (*recv_len).wrapping_sub(1u32) as (isize) + ) as (i32); + } else { + *sw = 0i32; + } + Enum5::YKPIV_OK +} + +#[derive(Clone, Copy)] +#[repr(i32)] +pub enum Enum6 { + DES_OK = 0i32, + DES_INVALID_PARAMETER = -1i32, + DES_BUFFER_TOO_SMALL = -2i32, + DES_MEMORY_ERROR = -3i32, + DES_GENERAL_ERROR = -4i32, +} + +#[no_mangle] +pub unsafe extern fn ykpiv_authenticate( + mut state : *mut ykpiv_state, mut key : *const u8 +) -> Enum5 { + let mut apdu : u_APDU; + let mut data : [u8; 261]; + let mut challenge : [u8; 8]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + let mut sw : i32; + let mut res : Enum5; + let mut drc : Enum6 = Enum6::DES_OK; + let mut mgm_key + : *mut des_key + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut des_key); + let mut out_len : usize = 0usize; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) == key { + key = (*b"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\0").as_ptr( + ); + } + if Enum6::DES_OK as (i32) != des_import_key( + 1i32, + key, + (8i32 * 3i32) as (usize), + &mut mgm_key as (*mut *mut des_key) + ) as (i32) { + res = Enum5::YKPIV_ALGORITHM_ERROR; + } else { + let mut response : [u8; 8]; + out_len = ::std::mem::size_of::<[u8; 8]>(); + drc = des_encrypt( + mgm_key, + challenge.as_mut_ptr() as (*const u8), + ::std::mem::size_of::<[u8; 8]>(), + response.as_mut_ptr(), + &mut out_len as (*mut usize) + ); + if drc as (i32) != Enum6::DES_OK as (i32) { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } else if memcmp( + response.as_mut_ptr() as (*const ::std::os::raw::c_void), + data.as_mut_ptr().offset( + 4isize + ) as (*const ::std::os::raw::c_void), + 8usize + ) == 0i32 { + res = Enum5::YKPIV_OK; + } else { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } + } + } + if !mgm_key.is_null() { + des_destroy_key(mgm_key); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_set_mgmkey( + mut state : *mut ykpiv_state, mut new_key : *const u8 +) -> Enum5 { + ykpiv_set_mgmkey2(state,new_key,0u8) +} + +#[no_mangle] +pub unsafe extern fn ykpiv_set_mgmkey2( + mut state : *mut ykpiv_state, mut new_key : *const u8, touch : u8 +) -> Enum5 { + let mut apdu : u_APDU; + let mut data : [u8; 261]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + let mut sw : i32; + let mut res : Enum5 = Enum5::YKPIV_OK; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if yk_des_is_weak_key(new_key,(8i32 * 3i32) as (usize)) { + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Won\'t set new key \'\0").as_ptr()); + dump_hex(new_key,(8i32 * 3i32) as (u32)); + fprintf( + __stderrp, + (*b"\' since it\'s weak (with odd parity).\n\0").as_ptr() + ); + } + res = Enum5::YKPIV_KEY_ERROR; + } else if !({ + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32)) { + if !(sw == 0x9000i32) { + res = Enum5::YKPIV_GENERIC_ERROR; + } + } + } + memset_s( + &mut apdu as (*mut u_APDU) as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::(), + 0i32, + ::std::mem::size_of::() + ); + _ykpiv_end_transaction(state); + res + } +} + +static mut hex_translate + : *mut u8 + = (*b"0123456789abcdef\0").as_ptr() as (*mut u8); + +#[no_mangle] +pub unsafe extern fn ykpiv_hex_decode( + mut hex_in : *const u8, + mut in_len : usize, + mut hex_out : *mut u8, + mut out_len : *mut usize +) -> Enum5 { + let mut _currentBlock; + let mut i : usize; + let mut first : bool = true; + if *out_len < in_len.wrapping_div(2usize) { + Enum5::YKPIV_SIZE_ERROR + } else if in_len.wrapping_rem(2usize) != 0usize { + Enum5::YKPIV_SIZE_ERROR + } else { + *out_len = in_len.wrapping_div(2usize); + i = 0usize; + 'loop3: loop { + if !(i < in_len) { + _currentBlock = 4; + break; + } + let mut ind_ptr + : *mut u8 + = strchr( + hex_translate as (*const u8), + tolower( + *{ + let _old = hex_in; + hex_in = hex_in.offset(1isize); + _old + } as (i32) + ) + ); + let mut index : i32 = 0i32; + if ind_ptr.is_null() { + _currentBlock = 6; + break; + } + index = ((ind_ptr as (isize)).wrapping_sub( + hex_translate as (isize) + ) / ::std::mem::size_of::() as (isize)) as (i32); + if first { + *hex_out = (index << 4i32) as (u8); + } else { + let _rhs = index; + let _lhs + = &mut *{ + let _old = hex_out; + hex_out = hex_out.offset(1isize); + _old + }; + *_lhs = (*_lhs as (i32) | _rhs) as (u8); + } + first = !first; + i = i.wrapping_add(1usize); + } + (if _currentBlock == 4 { + Enum5::YKPIV_OK + } else { + Enum5::YKPIV_PARSE_ERROR + }) + } +} + +unsafe extern fn _general_authenticate( + mut state : *mut ykpiv_state, + mut sign_in : *const u8, + mut in_len : usize, + mut out : *mut u8, + mut out_len : *mut usize, + mut algorithm : u8, + mut key : u8, + mut decipher : bool +) -> Enum5 { + let mut _currentBlock; + let mut indata : [u8; 1024]; + let mut dataptr : *mut u8 = indata.as_mut_ptr(); + let mut data : [u8; 1024]; + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut recv_len : usize = ::std::mem::size_of::<[u8; 1024]>(); + let mut key_len : usize = 0usize; + let mut sw : i32 = 0i32; + let mut bytes : usize; + let mut len : usize = 0usize; + let mut res : Enum5; + if algorithm as (i32) == 0x14i32 { + _currentBlock = 12; + } else if algorithm as (i32) == 0x11i32 { + key_len = 32usize; + _currentBlock = 12; + } else { + if !(algorithm as (i32) == 0x7i32) { + if algorithm as (i32) == 0x6i32 { + key_len = 128usize; + } else { + return Enum5::YKPIV_ALGORITHM_ERROR; + } + } + if key_len == 0usize { + key_len = 256usize; + } + if in_len != key_len { + return Enum5::YKPIV_SIZE_ERROR; + } else { + _currentBlock = 16; + } + } + if _currentBlock == 12 { + if key_len == 0usize { + key_len = 48usize; + } + if !decipher && (in_len > key_len) { + return Enum5::YKPIV_SIZE_ERROR; + } else if decipher && (in_len != key_len.wrapping_mul( + 2usize + ).wrapping_add( + 1usize + )) { + return Enum5::YKPIV_SIZE_ERROR; + } + } + if in_len < 0x80usize { + bytes = 1usize; + } else if in_len < 0xffusize { + bytes = 2usize; + } else { + bytes = 3usize; + } + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 0x7cu8; + dataptr = dataptr.offset( + _ykpiv_set_length( + dataptr, + in_len.wrapping_add(bytes).wrapping_add(3usize) + ) as (isize) + ); + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 0x82u8; + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 0x0u8; + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = if (algorithm as (i32) == 0x11i32 || algorithm as (i32) == 0x14i32) && decipher { + 0x85i32 + } else { + 0x81i32 + } as (u8); + dataptr = dataptr.offset( + _ykpiv_set_length(dataptr,in_len) as (isize) + ); + memcpy( + dataptr as (*mut ::std::os::raw::c_void), + sign_in as (*const ::std::os::raw::c_void), + in_len + ); + dataptr = dataptr.offset(in_len as (isize)); + if { + res = ykpiv_transfer_data( + state, + templ as (*const u8), + indata.as_mut_ptr() as (*const u8), + (dataptr as (isize)).wrapping_sub( + indata.as_mut_ptr() as (isize) + ) / ::std::mem::size_of::() as (isize), + data.as_mut_ptr(), + &mut recv_len as (*mut usize), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Sign command failed to communicate.\n\0").as_ptr() + ); + } + res + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed sign command with code %x.\n\0").as_ptr(), + sw + ); + } + (if sw == 0x6982i32 { + Enum5::YKPIV_AUTHENTICATION_ERROR + } else { + Enum5::YKPIV_GENERIC_ERROR + }) + } else if data[0usize] as (i32) != 0x7ci32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed parsing signature reply.\n\0").as_ptr() + ); + } + Enum5::YKPIV_PARSE_ERROR + } else { + dataptr = data.as_mut_ptr().offset(1isize); + dataptr = dataptr.offset( + _ykpiv_get_length( + dataptr as (*const u8), + &mut len as (*mut usize) + ) as (isize) + ); + (if *dataptr as (i32) != 0x82i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed parsing signature reply.\n\0").as_ptr() + ); + } + Enum5::YKPIV_PARSE_ERROR + } else { + dataptr = dataptr.offset(1isize); + dataptr = dataptr.offset( + _ykpiv_get_length( + dataptr as (*const u8), + &mut len as (*mut usize) + ) as (isize) + ); + (if len > *out_len { + if (*state).verbose != 0 { + fprintf(__stderrp,(*b"Wrong size on output buffer.\n\0").as_ptr()); + } + Enum5::YKPIV_SIZE_ERROR + } else { + *out_len = len; + memcpy( + out as (*mut ::std::os::raw::c_void), + dataptr as (*const ::std::os::raw::c_void), + len + ); + Enum5::YKPIV_OK + }) + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_sign_data( + mut state : *mut ykpiv_state, + mut raw_in : *const u8, + mut in_len : usize, + mut sign_out : *mut u8, + mut out_len : *mut usize, + mut algorithm : u8, + mut key : u8 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + res = _general_authenticate( + state, + raw_in, + in_len, + sign_out, + out_len, + algorithm, + key, + false + ); + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_decipher_data( + mut state : *mut ykpiv_state, + mut in_ : *const u8, + mut in_len : usize, + mut out : *mut u8, + mut out_len : *mut usize, + mut algorithm : u8, + mut key : u8 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + res = _general_authenticate( + state, + in_, + in_len, + out, + out_len, + algorithm, + key, + true + ); + _ykpiv_end_transaction(state); + res + } +} + +unsafe extern fn _ykpiv_get_version( + mut state : *mut ykpiv_state, mut p_version : *mut _ykpiv_version_t +) -> Enum5 { + let mut apdu : u_APDU; + let mut data : [u8; 261]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + let mut sw : i32; + let mut res : Enum5; + if state.is_null() { + Enum5::YKPIV_ARGUMENT_ERROR + } else if (*state).ver.major != 0 || (*state).ver.minor != 0 || (*state).ver.patch != 0 { + if !p_version.is_null() { + memcpy( + p_version as (*mut ::std::os::raw::c_void), + &mut (*state).ver as (*mut _ykpiv_version_t) as (*const ::std::os::raw::c_void), + ::std::mem::size_of::<_ykpiv_version_t>() + ); + } + Enum5::YKPIV_OK + } else if { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + res + } else { + if sw == 0x9000i32 { + if recv_len < 3u32 { + return Enum5::YKPIV_SIZE_ERROR; + } else { + (*state).ver.major = data[0usize]; + (*state).ver.minor = data[1usize]; + (*state).ver.patch = data[2usize]; + if !p_version.is_null() { + memcpy( + p_version as (*mut ::std::os::raw::c_void), + &mut (*state).ver as (*mut _ykpiv_version_t) as (*const ::std::os::raw::c_void), + ::std::mem::size_of::<_ykpiv_version_t>() + ); + } + } + } else { + res = Enum5::YKPIV_GENERIC_ERROR; + } + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_get_version( + mut state : *mut ykpiv_state, + mut version : *mut u8, + mut len : usize +) -> Enum5 { + let mut res : Enum5; + let mut result : i32 = 0i32; + let mut ver + : _ykpiv_version_t + = _ykpiv_version_t { major: 0u8, minor: 0u8, patch: 0u8 }; + if { + res = _ykpiv_begin_transaction(state); + res + } as (i32) < Enum5::YKPIV_OK as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !({ + res = _ykpiv_ensure_application_selected(state); + res + } as (i32) < Enum5::YKPIV_OK as (i32)) { + if { + res = _ykpiv_get_version( + state, + &mut ver as (*mut _ykpiv_version_t) + ); + res + } as (i32) >= Enum5::YKPIV_OK as (i32) { + result = snprintf( + version, + len, + (*b"%d.%d.%d\0").as_ptr(), + ver.major as (i32), + ver.minor as (i32), + ver.patch as (i32) + ); + if result < 0i32 { + res = Enum5::YKPIV_SIZE_ERROR; + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +unsafe extern fn _ykpiv_get_serial( + mut state : *mut ykpiv_state, + mut p_serial : *mut u32, + mut f_force : bool +) -> Enum5 { + let mut _currentBlock; + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut apdu : u_APDU; + let mut yk_applet : *const u8 = 0xa0i32 as (*const u8); + let mut data : [u8; 255]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 255]>() as (u32); + let mut sw : i32; + let mut p_temp + : *mut u8 + = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + if state.is_null() { + Enum5::YKPIV_ARGUMENT_ERROR + } else if !f_force && ((*state).serial != 0u32) { + if !p_serial.is_null() { + *p_serial = (*state).serial; + } + Enum5::YKPIV_OK + } else { + if (*state).ver.major as (i32) < 5i32 { + let mut temp : [u8; 255]; + recv_len = ::std::mem::size_of::<[u8; 255]>() as (u32); + if { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + temp.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) < Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed communicating with card: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + _currentBlock = 37; + } else { + _currentBlock = 37; + } + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed selecting yk application: %04x\n\0").as_ptr(), + sw + ); + } + res = Enum5::YKPIV_GENERIC_ERROR; + _currentBlock = 37; + } else { + recv_len = ::std::mem::size_of::<[u8; 255]>() as (u32); + if { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) < Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed communicating with card: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + _currentBlock = 37; + } else { + _currentBlock = 37; + } + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed retrieving serial number: %04x\n\0").as_ptr(), + sw + ); + } + res = Enum5::YKPIV_GENERIC_ERROR; + _currentBlock = 37; + } else { + recv_len = ::std::mem::size_of::<[u8; 255]>() as (u32); + if { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + temp.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) < Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed communicating with card: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + } + return res; + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed selecting application: %04x\n\0").as_ptr(), + sw + ); + } + return Enum5::YKPIV_GENERIC_ERROR; + } + _currentBlock = 17; + } + } + } else { + if { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed communicating with card: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + } + return res; + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed retrieving serial number: %04x\n\0").as_ptr(), + sw + ); + } + return Enum5::YKPIV_GENERIC_ERROR; + } + _currentBlock = 17; + } + if _currentBlock == 17 { + if recv_len < 4u32 { + return Enum5::YKPIV_SIZE_ERROR; + } else { + p_temp = &mut (*state).serial as (*mut u32) as (*mut u8); + *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + } = data[3usize]; + *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + } = data[2usize]; + *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + } = data[1usize]; + *{ + let _old = p_temp; + p_temp = p_temp.offset(1isize); + _old + } = data[0usize]; + if !p_serial.is_null() { + *p_serial = (*state).serial; + } + } + } + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_get_serial( + mut state : *mut ykpiv_state, mut p_serial : *mut u32 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + if { + res = _ykpiv_begin_transaction(state); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !({ + res = _ykpiv_ensure_application_selected(state); + res + } as (i32) != Enum5::YKPIV_OK as (i32)) { + res = _ykpiv_get_serial(state,p_serial,false); + } + _ykpiv_end_transaction(state); + res + } +} + +unsafe extern fn _cache_pin( + mut state : *mut ykpiv_state, mut pin : *const u8, mut len : usize +) -> Enum5 { + if state.is_null() { + Enum5::YKPIV_ARGUMENT_ERROR + } else if !pin.is_null() && ((*state).pin as (*const u8) == pin) { + Enum5::YKPIV_OK + } else { + if !(*state).pin.is_null() { + memset_s( + (*state).pin as (*mut ::std::os::raw::c_void), + strnlen((*state).pin as (*const u8),8usize), + 0i32, + strnlen((*state).pin as (*const u8),8usize) + ); + _ykpiv_free(state,(*state).pin as (*mut ::std::os::raw::c_void)); + (*state).pin = 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8); + } + if !pin.is_null() && (len > 0usize) { + (*state).pin = _ykpiv_alloc( + state, + len.wrapping_mul(::std::mem::size_of::()).wrapping_add(1usize) + ) as (*mut u8); + if (*state).pin == 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) { + return Enum5::YKPIV_MEMORY_ERROR; + } else { + memcpy( + (*state).pin as (*mut ::std::os::raw::c_void), + pin as (*const ::std::os::raw::c_void), + len + ); + *(*state).pin.offset(len as (isize)) = 0u8; + } + } + Enum5::YKPIV_OK + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_verify( + mut state : *mut ykpiv_state, + mut pin : *const u8, + mut tries : *mut i32 +) -> Enum5 { + ykpiv_verify_select( + state, + pin, + if !pin.is_null() { strlen(pin) } else { 0usize }, + tries, + false + ) +} + +unsafe extern fn _verify( + mut state : *mut ykpiv_state, + mut pin : *const u8, + pin_len : usize, + mut tries : *mut i32 +) -> Enum5 { + let mut apdu : u_APDU; + let mut data : [u8; 261]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + let mut sw : i32; + let mut res : Enum5; + if pin_len > 8usize { + Enum5::YKPIV_SIZE_ERROR + } else { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + memset_s( + &mut apdu as (*mut u_APDU) as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::(), + 0i32, + ::std::mem::size_of::() + ); + (if res as (i32) != Enum5::YKPIV_OK as (i32) { + res + } else if sw == 0x9000i32 { + if !pin.is_null() && (pin_len != 0) { + _cache_pin(state,pin,pin_len); + } + if !tries.is_null() { + *tries = sw & 0xfi32; + } + Enum5::YKPIV_OK + } else if sw >> 8i32 == 0x63i32 { + if !tries.is_null() { + *tries = sw & 0xfi32; + } + Enum5::YKPIV_WRONG_PIN + } else if sw == 0x6983i32 { + if !tries.is_null() { + *tries = 0i32; + } + Enum5::YKPIV_WRONG_PIN + } else { + Enum5::YKPIV_GENERIC_ERROR + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_verify_select( + mut state : *mut ykpiv_state, + mut pin : *const u8, + pin_len : usize, + mut tries : *mut i32, + mut force_select : bool +) -> Enum5 { + let mut _currentBlock; + let mut res : Enum5 = Enum5::YKPIV_OK; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if force_select { + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32) { + _currentBlock = 4; + } else { + _currentBlock = 3; + } + } else { + _currentBlock = 3; + } + if _currentBlock == 3 { + res = _verify(state,pin,pin_len,tries); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_get_pin_retries( + mut state : *mut ykpiv_state, mut tries : *mut i32 +) -> Enum5 { + let mut res : Enum5; + let mut ykrc : Enum5; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state || 0i32 as (*mut ::std::os::raw::c_void) as (*mut i32) == tries { + Enum5::YKPIV_ARGUMENT_ERROR + } else { + res = _ykpiv_select_application(state); + (if res as (i32) != Enum5::YKPIV_OK as (i32) { + res + } else { + ykrc = ykpiv_verify( + state, + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8), + tries + ); + (if ykrc as (i32) == Enum5::YKPIV_WRONG_PIN as (i32) { + Enum5::YKPIV_OK as (i32) + } else { + ykrc as (i32) + }) as (Enum5) + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_set_pin_retries( + mut state : *mut ykpiv_state, + mut pin_tries : i32, + mut puk_tries : i32 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut data : [u8; 255]; + let mut recv_len : usize = ::std::mem::size_of::<[u8; 255]>(); + let mut sw : i32 = 0i32; + if pin_tries == 0i32 || puk_tries == 0i32 { + Enum5::YKPIV_OK + } else if pin_tries > 0xffi32 || puk_tries > 0xffi32 || pin_tries < 1i32 || puk_tries < 1i32 { + Enum5::YKPIV_RANGE_ERROR + } else { + *templ.offset(2isize) = pin_tries as (u8); + *templ.offset(3isize) = puk_tries as (u8); + (if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = ykpiv_transfer_data( + state, + templ as (*const u8), + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8), + 0isize, + data.as_mut_ptr(), + &mut recv_len as (*mut usize), + &mut sw as (*mut i32) + ); + if Enum5::YKPIV_OK as (i32) == res as (i32) { + if !(0x9000i32 == sw) { + if sw == 0x6983i32 { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } else if sw == 0x6982i32 { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } else { + res = Enum5::YKPIV_GENERIC_ERROR; + } + } + } + } + _ykpiv_end_transaction(state); + res + }) + } +} + +unsafe extern fn _ykpiv_change_pin( + mut state : *mut ykpiv_state, + mut action : i32, + mut current_pin : *const u8, + mut current_pin_len : usize, + mut new_pin : *const u8, + mut new_pin_len : usize, + mut tries : *mut i32 +) -> Enum5 { + let mut sw : i32; + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut indata : [u8; 16]; + let mut data : [u8; 255]; + let mut recv_len : usize = ::std::mem::size_of::<[u8; 255]>(); + let mut res : Enum5; + if current_pin_len > 8usize { + Enum5::YKPIV_SIZE_ERROR + } else if new_pin_len > 8usize { + Enum5::YKPIV_SIZE_ERROR + } else { + if action == 1i32 { + *templ.offset(1isize) = 0x2cu8; + } else if action == 2i32 { + *templ.offset(3isize) = 0x81u8; + } + memcpy( + indata.as_mut_ptr() as (*mut ::std::os::raw::c_void), + current_pin as (*const ::std::os::raw::c_void), + current_pin_len + ); + if current_pin_len < 8usize { + memset( + indata.as_mut_ptr().offset( + current_pin_len as (isize) + ) as (*mut ::std::os::raw::c_void), + 0xffi32, + 8usize.wrapping_sub(current_pin_len) + ); + } + memcpy( + indata.as_mut_ptr().offset( + 8isize + ) as (*mut ::std::os::raw::c_void), + new_pin as (*const ::std::os::raw::c_void), + new_pin_len + ); + if new_pin_len < 8usize { + memset( + indata.as_mut_ptr().offset(8isize).offset( + new_pin_len as (isize) + ) as (*mut ::std::os::raw::c_void), + 0xffi32, + 8usize.wrapping_sub(new_pin_len) + ); + } + res = ykpiv_transfer_data( + state, + templ as (*const u8), + indata.as_mut_ptr() as (*const u8), + ::std::mem::size_of::<[u8; 16]>() as (isize), + data.as_mut_ptr(), + &mut recv_len as (*mut usize), + &mut sw as (*mut i32) + ); + memset_s( + indata.as_mut_ptr() as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 16]>(), + 0i32, + ::std::mem::size_of::<[u8; 16]>() + ); + (if res as (i32) != Enum5::YKPIV_OK as (i32) { + res + } else if sw != 0x9000i32 { + (if sw >> 8i32 == 0x63i32 { + if !tries.is_null() { + *tries = sw & 0xfi32; + } + Enum5::YKPIV_WRONG_PIN + } else if sw == 0x6983i32 { + Enum5::YKPIV_PIN_LOCKED + } else { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed changing pin, token response code: %x.\n\0").as_ptr(), + sw + ); + } + Enum5::YKPIV_GENERIC_ERROR + }) + } else { + Enum5::YKPIV_OK + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_change_pin( + mut state : *mut ykpiv_state, + mut current_pin : *const u8, + mut current_pin_len : usize, + mut new_pin : *const u8, + mut new_pin_len : usize, + mut tries : *mut i32 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_GENERIC_ERROR; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _ykpiv_change_pin( + state, + 0i32, + current_pin, + current_pin_len, + new_pin, + new_pin_len, + tries + ); + if res as (i32) == Enum5::YKPIV_OK as (i32) && (new_pin != 0i32 as (*mut ::std::os::raw::c_void) as (*const u8)) { + _cache_pin(state,new_pin,new_pin_len); + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_change_puk( + mut state : *mut ykpiv_state, + mut current_puk : *const u8, + mut current_puk_len : usize, + mut new_puk : *const u8, + mut new_puk_len : usize, + mut tries : *mut i32 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_GENERIC_ERROR; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _ykpiv_change_pin( + state, + 2i32, + current_puk, + current_puk_len, + new_puk, + new_puk_len, + tries + ); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_unblock_pin( + mut state : *mut ykpiv_state, + mut puk : *const u8, + mut puk_len : usize, + mut new_pin : *const u8, + mut new_pin_len : usize, + mut tries : *mut i32 +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_GENERIC_ERROR; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _ykpiv_change_pin( + state, + 1i32, + puk, + puk_len, + new_pin, + new_pin_len, + tries + ); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_fetch_object( + mut state : *mut ykpiv_state, + mut object_id : i32, + mut data : *mut u8, + mut len : *mut usize +) -> Enum5 { + let mut res : Enum5; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _ykpiv_fetch_object(state,object_id,data,len); + } + _ykpiv_end_transaction(state); + res + } +} + +unsafe extern fn set_object( + mut object_id : i32, mut buffer : *mut u8 +) -> *mut u8 { + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = 0x5cu8; + if object_id == 0x7ei32 { + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = 1u8; + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = 0x7eu8; + } else if object_id > 0xffffi32 && (object_id <= 0xffffffi32) { + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = 3u8; + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = (object_id >> 16i32 & 0xffi32) as (u8); + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = (object_id >> 8i32 & 0xffi32) as (u8); + *{ + let _old = buffer; + buffer = buffer.offset(1isize); + _old + } = (object_id & 0xffi32) as (u8); + } + buffer +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_fetch_object( + mut state : *mut ykpiv_state, + mut object_id : i32, + mut data : *mut u8, + mut len : *mut usize +) -> Enum5 { + let mut sw : i32; + let mut indata : [u8; 5]; + let mut inptr : *mut u8 = indata.as_mut_ptr(); + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut res : Enum5; + inptr = set_object(object_id,inptr); + if inptr == 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) { + Enum5::YKPIV_INVALID_OBJECT + } else if { + res = ykpiv_transfer_data( + state, + templ as (*const u8), + indata.as_mut_ptr() as (*const u8), + (inptr as (isize)).wrapping_sub( + indata.as_mut_ptr() as (isize) + ) / ::std::mem::size_of::() as (isize), + data, + len, + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + res + } else if sw == 0x9000i32 { + let mut outlen : usize = 0usize; + let mut offs : u32 = 0u32; + (if *len < 2usize || !_ykpiv_has_valid_length( + data.offset(1isize) as (*const u8), + (*len).wrapping_sub(1usize) + ) { + Enum5::YKPIV_SIZE_ERROR + } else { + offs = _ykpiv_get_length( + data.offset(1isize) as (*const u8), + &mut outlen as (*mut usize) + ); + (if offs == 0u32 { + Enum5::YKPIV_SIZE_ERROR + } else if outlen.wrapping_add(offs as (usize)).wrapping_add( + 1usize + ) != *len { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Invalid length indicated in object, total objlen is %lu, indicated length is %lu.\0").as_ptr( + ), + *len, + outlen + ); + } + Enum5::YKPIV_SIZE_ERROR + } else { + memmove( + data as (*mut ::std::os::raw::c_void), + data.offset(1isize).offset( + offs as (isize) + ) as (*const ::std::os::raw::c_void), + outlen + ); + *len = outlen; + Enum5::YKPIV_OK + }) + }) + } else { + Enum5::YKPIV_GENERIC_ERROR + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_save_object( + mut state : *mut ykpiv_state, + mut object_id : i32, + mut indata : *mut u8, + mut len : usize +) -> Enum5 { + let mut res : Enum5; + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + res = _ykpiv_save_object(state,object_id,indata,len); + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn _ykpiv_save_object( + mut state : *mut ykpiv_state, + mut object_id : i32, + mut indata : *mut u8, + mut len : usize +) -> Enum5 { + let mut data : [u8; 3072]; + let mut dataptr : *mut u8 = data.as_mut_ptr(); + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut sw : i32; + let mut res : Enum5; + let mut outlen : usize = 0usize; + if len > ::std::mem::size_of::<[u8; 3072]>().wrapping_sub(9usize) { + Enum5::YKPIV_SIZE_ERROR + } else { + dataptr = set_object(object_id,dataptr); + (if dataptr == 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) { + Enum5::YKPIV_INVALID_OBJECT + } else { + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 0x53u8; + dataptr = dataptr.offset( + _ykpiv_set_length(dataptr,len) as (isize) + ); + memcpy( + dataptr as (*mut ::std::os::raw::c_void), + indata as (*const ::std::os::raw::c_void), + len + ); + dataptr = dataptr.offset(len as (isize)); + (if { + res = _ykpiv_transfer_data( + state, + templ as (*const u8), + data.as_mut_ptr() as (*const u8), + (dataptr as (isize)).wrapping_sub( + data.as_mut_ptr() as (isize) + ) / ::std::mem::size_of::() as (isize), + 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8), + &mut outlen as (*mut usize), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32) { + res + } else if 0x9000i32 == sw { + Enum5::YKPIV_OK + } else if 0x6982i32 == sw { + Enum5::YKPIV_AUTHENTICATION_ERROR + } else { + Enum5::YKPIV_GENERIC_ERROR + }) + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_import_private_key( + mut state : *mut ykpiv_state, + key : u8, + mut algorithm : u8, + mut p : *const u8, + mut p_len : usize, + mut q : *const u8, + mut q_len : usize, + mut dp : *const u8, + mut dp_len : usize, + mut dq : *const u8, + mut dq_len : usize, + mut qinv : *const u8, + mut qinv_len : usize, + mut ec_data : *const u8, + mut ec_data_len : u8, + pin_policy : u8, + touch_policy : u8 +) -> Enum5 { + let mut _currentBlock; + let mut key_data : [u8; 1024]; + let mut in_ptr : *mut u8 = key_data.as_mut_ptr(); + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut data : [u8; 256]; + let mut recv_len : usize = ::std::mem::size_of::<[u8; 256]>(); + let mut elem_len : u32; + let mut sw : i32; + let mut params : [*const u8; 5]; + let mut lens : [usize; 5]; + let mut padding : usize; + let mut n_params : u8; + let mut i : i32; + let mut param_tag : i32; + let mut res : Enum5; + if state == 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) { + Enum5::YKPIV_GENERIC_ERROR + } else if key as (i32) == 0x9bi32 || key as (i32) < 0x82i32 || key as (i32) > 0x95i32 && (key as (i32) < 0x9ai32) || key as (i32) > 0x9ei32 && (key as (i32) != 0xf9i32) { + Enum5::YKPIV_KEY_ERROR + } else if pin_policy as (i32) != 0i32 && (pin_policy as (i32) != 1i32) && (pin_policy as (i32) != 2i32) && (pin_policy as (i32) != 3i32) { + Enum5::YKPIV_GENERIC_ERROR + } else if touch_policy as (i32) != 0i32 && (touch_policy as (i32) != 1i32) && (touch_policy as (i32) != 2i32) && (touch_policy as (i32) != 3i32) { + Enum5::YKPIV_GENERIC_ERROR + } else { + if algorithm as (i32) == 0x6i32 || algorithm as (i32) == 0x7i32 { + if p_len.wrapping_add(q_len).wrapping_add(dp_len).wrapping_add( + dq_len + ).wrapping_add( + qinv_len + ) >= ::std::mem::size_of::<[u8; 1024]>() { + return Enum5::YKPIV_SIZE_ERROR; + } else { + if algorithm as (i32) == 0x6i32 { + elem_len = 64u32; + } + if algorithm as (i32) == 0x7i32 { + elem_len = 128u32; + } + if p == 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) || q == 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) || dp == 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) || dq == 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) || qinv == 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) { + return Enum5::YKPIV_GENERIC_ERROR; + } else { + params[0usize] = p; + lens[0usize] = p_len; + params[1usize] = q; + lens[1usize] = q_len; + params[2usize] = dp; + lens[2usize] = dp_len; + params[3usize] = dq; + lens[3usize] = dq_len; + params[4usize] = qinv; + lens[4usize] = qinv_len; + param_tag = 0x1i32; + n_params = 5u8; + } + } + } else if algorithm as (i32) == 0x11i32 || algorithm as (i32) == 0x14i32 { + if ec_data_len as (usize) >= ::std::mem::size_of::<[u8; 1024]>() { + return Enum5::YKPIV_SIZE_ERROR; + } else { + if algorithm as (i32) == 0x11i32 { + elem_len = 32u32; + } + if algorithm as (i32) == 0x14i32 { + elem_len = 48u32; + } + if ec_data == 0i32 as (*mut ::std::os::raw::c_void) as (*const u8) { + return Enum5::YKPIV_GENERIC_ERROR; + } else { + params[0usize] = ec_data; + lens[0usize] = ec_data_len as (usize); + param_tag = 0x6i32; + n_params = 1u8; + } + } + } else { + return Enum5::YKPIV_ALGORITHM_ERROR; + } + i = 0i32; + 'loop24: loop { + if !(i < n_params as (i32)) { + _currentBlock = 25; + break; + } + let mut remaining : usize; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = (param_tag + i) as (u8); + in_ptr = in_ptr.offset( + _ykpiv_set_length(in_ptr,elem_len as (usize)) as (isize) + ); + padding = (elem_len as (usize)).wrapping_sub(lens[i as (usize)]); + remaining = (key_data.as_mut_ptr() as (usize)).wrapping_add( + ::std::mem::size_of::<[u8; 1024]>() + ).wrapping_sub( + in_ptr as (usize) + ); + if padding > remaining { + _currentBlock = 39; + break; + } + memset(in_ptr as (*mut ::std::os::raw::c_void),0i32,padding); + in_ptr = in_ptr.offset(padding as (isize)); + memcpy( + in_ptr as (*mut ::std::os::raw::c_void), + params[i as (usize)] as (*const ::std::os::raw::c_void), + lens[i as (usize)] + ); + in_ptr = in_ptr.offset(lens[i as (usize)] as (isize)); + i = i + 1; + } + if _currentBlock == 25 { + if pin_policy as (i32) != 0i32 { + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0xaau8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0x1u8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = pin_policy; + } + if touch_policy as (i32) != 0i32 { + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0xabu8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = 0x1u8; + *{ + let _old = in_ptr; + in_ptr = in_ptr.offset(1isize); + _old + } = touch_policy; + } + if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + return Enum5::YKPIV_PCSC_ERROR; + } else if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected( + state + ); + res + } as (i32)) { + if !({ + res = ykpiv_transfer_data( + state, + templ as (*const u8), + key_data.as_mut_ptr() as (*const u8), + (in_ptr as (isize)).wrapping_sub( + key_data.as_mut_ptr() as (isize) + ) / ::std::mem::size_of::() as (isize), + data.as_mut_ptr(), + &mut recv_len as (*mut usize), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32)) { + if 0x9000i32 != sw { + res = Enum5::YKPIV_GENERIC_ERROR; + if sw == 0x6982i32 { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } + } + } + } + } else { + res = Enum5::YKPIV_ALGORITHM_ERROR; + } + memset_s( + key_data.as_mut_ptr() as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::<[u8; 1024]>(), + 0i32, + ::std::mem::size_of::<[u8; 1024]>() + ); + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_attest( + mut state : *mut ykpiv_state, + key : u8, + mut data : *mut u8, + mut data_len : *mut usize +) -> Enum5 { + let mut res : Enum5; + let mut templ : *mut u8 = 0i32 as (*mut u8); + let mut sw : i32; + let mut ul_data_len : usize; + if state == 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) || data == 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) || data_len == 0i32 as (*mut ::std::os::raw::c_void) as (*mut usize) { + Enum5::YKPIV_ARGUMENT_ERROR + } else { + ul_data_len = *data_len; + (if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if !({ + res = ykpiv_transfer_data( + state, + templ as (*const u8), + 0i32 as (*mut ::std::os::raw::c_void) as (*const u8), + 0isize, + data, + &mut ul_data_len as (*mut usize), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32)) { + if 0x9000i32 != sw { + res = Enum5::YKPIV_GENERIC_ERROR; + if 0x6d00i32 == sw { + res = Enum5::YKPIV_NOT_SUPPORTED; + } + } else if *data.offset(0isize) as (i32) != 0x30i32 { + res = Enum5::YKPIV_GENERIC_ERROR; + } else { + *data_len = ul_data_len; + } + } + } + _ykpiv_end_transaction(state); + res + }) + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_auth_getchallenge( + mut state : *mut ykpiv_state, + mut challenge : *mut u8, + challenge_len : usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut apdu : u_APDU = 0i32 as (u_APDU); + let mut data : [u8; 261]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + let mut sw : i32 = 0i32; + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == challenge { + Enum5::YKPIV_GENERIC_ERROR + } else if 8usize != challenge_len { + Enum5::YKPIV_SIZE_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + if !(Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_ensure_application_selected(state); + res + } as (i32)) { + if !({ + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32)) { + if sw != 0x9000i32 { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } else { + memcpy( + challenge as (*mut ::std::os::raw::c_void), + data.as_mut_ptr().offset( + 4isize + ) as (*const ::std::os::raw::c_void), + 8usize + ); + } + } + } + _ykpiv_end_transaction(state); + res + } +} + +#[no_mangle] +pub unsafe extern fn ykpiv_auth_verifyresponse( + mut state : *mut ykpiv_state, + mut response : *mut u8, + response_len : usize +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut apdu : u_APDU = 0i32 as (u_APDU); + let mut data : [u8; 261]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 261]>() as (u32); + let mut sw : i32 = 0i32; + let mut dataptr : *mut u8 = 0i32 as (*mut u8); + if 0i32 as (*mut ::std::os::raw::c_void) as (*mut ykpiv_state) == state { + Enum5::YKPIV_GENERIC_ERROR + } else if 0i32 as (*mut ::std::os::raw::c_void) as (*mut u8) == response { + Enum5::YKPIV_GENERIC_ERROR + } else if 8usize != response_len { + Enum5::YKPIV_SIZE_ERROR + } else if Enum5::YKPIV_OK as (i32) != { + res = _ykpiv_begin_transaction(state); + res + } as (i32) { + Enum5::YKPIV_PCSC_ERROR + } else { + recv_len = ::std::mem::size_of::<[u8; 261]>() as (u32); + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 0x7cu8; + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 0xau8; + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 0x82u8; + *{ + let _old = dataptr; + dataptr = dataptr.offset(1isize); + _old + } = 8u8; + memcpy( + dataptr as (*mut ::std::os::raw::c_void), + response as (*const ::std::os::raw::c_void), + response_len + ); + dataptr = dataptr.offset(8isize); + if !({ + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) != Enum5::YKPIV_OK as (i32)) { + if sw != 0x9000i32 { + res = Enum5::YKPIV_AUTHENTICATION_ERROR; + } + } + memset_s( + &mut apdu as (*mut u_APDU) as (*mut ::std::os::raw::c_void), + ::std::mem::size_of::(), + 0i32, + ::std::mem::size_of::() + ); + _ykpiv_end_transaction(state); + res + } +} + +static mut MGMT_AID : *const u8 = 0xa0i32 as (*const u8); + +#[no_mangle] +pub unsafe extern fn ykpiv_auth_deauthenticate( + mut state : *mut ykpiv_state +) -> Enum5 { + let mut res : Enum5 = Enum5::YKPIV_OK; + let mut apdu : u_APDU; + let mut data : [u8; 255]; + let mut recv_len + : u32 + = ::std::mem::size_of::<[u8; 255]>() as (u32); + let mut sw : i32; + if state.is_null() { + Enum5::YKPIV_ARGUMENT_ERROR + } else if { + res = _ykpiv_begin_transaction(state); + res + } as (i32) < Enum5::YKPIV_OK as (i32) { + res + } else { + if { + res = _send_data( + state, + &mut apdu as (*mut u_APDU), + data.as_mut_ptr(), + &mut recv_len as (*mut u32), + &mut sw as (*mut i32) + ); + res + } as (i32) < Enum5::YKPIV_OK as (i32) { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed communicating with card: \'%s\'\n\0").as_ptr(), + ykpiv_strerror(res) + ); + } + } else if sw != 0x9000i32 { + if (*state).verbose != 0 { + fprintf( + __stderrp, + (*b"Failed selecting mgmt application: %04x\n\0").as_ptr(), + sw + ); + } + res = Enum5::YKPIV_GENERIC_ERROR; + } + _ykpiv_end_transaction(state); + res + } +}