1d86885ab1
This commit contains a multitude of fixes and some initial translation work so the first rustc pass compiles. It removes `unsafe extern "C"` declarations, so now there are a number of errors about invocations of unsafe functions that need to be addressed. They should each be scoped to an `unsafe` block so as to aid in an eventual safe translation. Some of the functions are now using the module system rather than `extern "C"` bindings, but the translation is not complete.
2868 lines
100 KiB
Rust
2868 lines
100 KiB
Rust
// Adapted from yubico-piv-tool:
|
|
// <https://github.com/Yubico/yubico-piv-tool/>
|
|
//
|
|
// Copyright (c) 2014-2016 Yubico AB
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
//
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following
|
|
// disclaimer in the documentation and/or other materials provided
|
|
// with the distribution.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
#![allow(non_camel_case_types)]
|
|
|
|
use crate::{
|
|
error::ErrorKind,
|
|
internal::{setting_get_bool, SettingBool, SettingSource},
|
|
};
|
|
use libc::{free, memcpy, memmove, time, time_t};
|
|
use std::{ffi::CString, mem, os::raw::c_void};
|
|
|
|
extern "C" {
|
|
static mut _DefaultRuneLocale: Struct1;
|
|
fn __maskrune(arg1: i32, arg2: usize) -> i32;
|
|
fn __tolower(arg1: i32) -> i32;
|
|
fn __toupper(arg1: i32) -> i32;
|
|
fn _ykpiv_alloc(state: *mut ykpiv_state, size: usize) -> *mut c_void;
|
|
fn _ykpiv_begin_transaction(state: *mut ykpiv_state) -> ErrorKind;
|
|
fn _ykpiv_end_transaction(state: *mut ykpiv_state) -> ErrorKind;
|
|
fn _ykpiv_ensure_application_selected(state: *mut ykpiv_state) -> ErrorKind;
|
|
fn _ykpiv_fetch_object(
|
|
state: *mut ykpiv_state,
|
|
object_id: i32,
|
|
data: *mut u8,
|
|
len: *mut usize,
|
|
) -> ErrorKind;
|
|
fn _ykpiv_free(state: *mut ykpiv_state, data: *mut 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 c_void, size: usize) -> *mut c_void;
|
|
fn _ykpiv_save_object(
|
|
state: *mut ykpiv_state,
|
|
object_id: i32,
|
|
indata: *mut u8,
|
|
len: usize,
|
|
) -> ErrorKind;
|
|
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,
|
|
) -> ErrorKind;
|
|
fn memset_s(__s: *mut 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 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,
|
|
) -> ErrorKind;
|
|
fn ykpiv_set_mgmkey(state: *mut ykpiv_state, new_key: *const u8) -> ErrorKind;
|
|
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,
|
|
) -> ErrorKind;
|
|
}
|
|
|
|
#[derive(Copy)]
|
|
#[repr(C)]
|
|
pub struct __sbuf {
|
|
pub _base: *mut u8,
|
|
pub _size: i32,
|
|
}
|
|
|
|
impl Clone for __sbuf {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
pub fn isascii(mut _c: i32) -> i32 {
|
|
(_c & !0x7fi32 == 0i32) as (i32)
|
|
}
|
|
|
|
#[derive(Copy)]
|
|
#[repr(C)]
|
|
pub struct Struct3 {
|
|
pub __min: i32,
|
|
pub __max: i32,
|
|
pub __map: i32,
|
|
pub __types: *mut u32,
|
|
}
|
|
|
|
impl Clone for Struct3 {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
#[derive(Copy)]
|
|
#[repr(C)]
|
|
pub struct Struct2 {
|
|
pub __nranges: i32,
|
|
pub __ranges: *mut Struct3,
|
|
}
|
|
|
|
impl Clone for Struct2 {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
#[derive(Copy)]
|
|
#[repr(C)]
|
|
pub struct Struct4 {
|
|
pub __name: [u8; 14],
|
|
pub __mask: u32,
|
|
}
|
|
|
|
impl Clone for Struct4 {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
#[derive(Copy)]
|
|
#[repr(C)]
|
|
pub struct Struct1 {
|
|
pub __magic: [u8; 8],
|
|
pub __encoding: [u8; 32],
|
|
pub __sgetrune: unsafe fn(*const u8, usize, *mut *const u8) -> i32,
|
|
pub __sputrune: unsafe 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 c_void,
|
|
pub __variable_len: i32,
|
|
pub __ncharclasses: i32,
|
|
pub __charclasses: *mut Struct4,
|
|
}
|
|
|
|
impl Clone for Struct1 {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
pub fn __istype(mut _c: i32, mut _f: usize) -> i32 {
|
|
if isascii(_c) != 0 {
|
|
!(_DefaultRuneLocale.__runetype[_c as (usize)] as (usize) & _f == 0) as (i32)
|
|
} else {
|
|
!(__maskrune(_c, _f) == 0) as (i32)
|
|
}
|
|
}
|
|
|
|
pub fn __isctype(mut _c: i32, mut _f: usize) -> i32 {
|
|
if _c < 0i32 || _c >= 256i32 {
|
|
0i32
|
|
} else {
|
|
!(_DefaultRuneLocale.__runetype[_c as (usize)] as (usize) & _f == 0) as (i32)
|
|
}
|
|
}
|
|
|
|
pub fn __wcwidth(mut _c: i32) -> i32 {
|
|
let mut _x: u32;
|
|
if _c == 0i32 {
|
|
0i32
|
|
} else {
|
|
_x = __maskrune(_c, 0xe0000000usize | 0x40000usize) as (u32);
|
|
(if _x as (usize) & 0xe0000000usize != 0usize {
|
|
((_x as (usize) & 0xe0000000usize) >> 30i32) as (i32)
|
|
} else if _x as (usize) & 0x40000usize != 0usize {
|
|
1i32
|
|
} else {
|
|
-1i32
|
|
})
|
|
}
|
|
}
|
|
|
|
pub fn isalnum(mut _c: i32) -> i32 {
|
|
__istype(_c, (0x100isize | 0x400isize) as (usize))
|
|
}
|
|
|
|
pub fn isalpha(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x100usize)
|
|
}
|
|
|
|
pub fn isblank(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x20000usize)
|
|
}
|
|
|
|
pub fn iscntrl(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x200usize)
|
|
}
|
|
|
|
pub fn isdigit(mut _c: i32) -> i32 {
|
|
__isctype(_c, 0x400usize)
|
|
}
|
|
|
|
pub fn isgraph(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x800usize)
|
|
}
|
|
|
|
pub fn islower(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x1000usize)
|
|
}
|
|
|
|
pub fn isprint(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x40000usize)
|
|
}
|
|
|
|
pub fn ispunct(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x2000usize)
|
|
}
|
|
|
|
pub fn isspace(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x4000usize)
|
|
}
|
|
|
|
pub fn isupper(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x8000usize)
|
|
}
|
|
|
|
pub fn isxdigit(mut _c: i32) -> i32 {
|
|
__isctype(_c, 0x10000usize)
|
|
}
|
|
|
|
pub fn toascii(mut _c: i32) -> i32 {
|
|
_c & 0x7fi32
|
|
}
|
|
|
|
pub fn tolower(mut _c: i32) -> i32 {
|
|
__tolower(_c)
|
|
}
|
|
|
|
pub fn toupper(mut _c: i32) -> i32 {
|
|
__toupper(_c)
|
|
}
|
|
|
|
pub fn digittoint(mut _c: i32) -> i32 {
|
|
__maskrune(_c, 0xfusize)
|
|
}
|
|
|
|
pub fn ishexnumber(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x10000usize)
|
|
}
|
|
|
|
pub fn isideogram(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x80000usize)
|
|
}
|
|
|
|
pub fn isnumber(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x400usize)
|
|
}
|
|
|
|
pub fn isphonogram(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x200000usize)
|
|
}
|
|
|
|
pub fn isrune(mut _c: i32) -> i32 {
|
|
__istype(_c, 0xfffffff0usize)
|
|
}
|
|
|
|
pub fn isspecial(mut _c: i32) -> i32 {
|
|
__istype(_c, 0x100000usize)
|
|
}
|
|
|
|
pub static mut CHUID_TMPL: *const u8 = 0x30i32 as (*const u8);
|
|
|
|
pub static mut CCC_TMPL: *const u8 = 0xf0i32 as (*const u8);
|
|
|
|
#[derive(Copy)]
|
|
#[repr(C)]
|
|
pub struct Struct6 {
|
|
pub data: [u8; 16],
|
|
}
|
|
|
|
impl Clone for Struct6 {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_get_cardid(mut state: *mut ykpiv_state, mut cardid: *mut Struct6) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut buf: [u8; 3063];
|
|
let mut len: usize = mem::size_of::<[u8; 3063]>();
|
|
if cardid.is_null() {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::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 ErrorKind::YKPIV_OK as (i32) == res as (i32) {
|
|
if len != 59usize {
|
|
res = ErrorKind::YKPIV_GENERIC_ERROR;
|
|
} else {
|
|
memcpy(
|
|
(*cardid).data.as_mut_ptr() as (*mut c_void),
|
|
buf.as_mut_ptr().offset(29isize) as (*const c_void),
|
|
16usize,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
#[repr(i32)]
|
|
pub enum Enum7 {
|
|
PRNG_OK = 0i32,
|
|
PRNG_GENERAL_ERROR = -1i32,
|
|
}
|
|
|
|
pub fn ykpiv_util_set_cardid(mut state: *mut ykpiv_state, mut cardid: *const Struct6) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut id: [u8; 16];
|
|
let mut buf: [u8; 59];
|
|
let mut len: usize = 0usize;
|
|
if state.is_null() {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
if cardid.is_null() {
|
|
if Enum7::PRNG_OK as (i32)
|
|
!= _ykpiv_prng_generate(id.as_mut_ptr(), mem::size_of::<[u8; 16]>()) as (i32)
|
|
{
|
|
return ErrorKind::YKPIV_RANDOMNESS_ERROR;
|
|
}
|
|
} else {
|
|
memcpy(
|
|
id.as_mut_ptr() as (*mut c_void),
|
|
(*cardid).data.as_mut_ptr() as (*const c_void),
|
|
mem::size_of::<[u8; 16]>(),
|
|
);
|
|
}
|
|
(if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
memcpy(
|
|
buf.as_mut_ptr() as (*mut c_void),
|
|
CHUID_TMPL as (*const c_void),
|
|
59usize,
|
|
);
|
|
memcpy(
|
|
buf.as_mut_ptr().offset(29isize) as (*mut c_void),
|
|
id.as_mut_ptr() as (*const c_void),
|
|
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
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_get_cccid(mut state: *mut ykpiv_state, mut ccc: *mut Struct8) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut buf: [u8; 3063];
|
|
let mut len: usize = mem::size_of::<[u8; 3063]>();
|
|
if ccc.is_null() {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::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 ErrorKind::YKPIV_OK as (i32) == res as (i32) {
|
|
if len != 51usize {
|
|
res = ErrorKind::YKPIV_GENERIC_ERROR;
|
|
} else {
|
|
memcpy(
|
|
(*ccc).data.as_mut_ptr() as (*mut c_void),
|
|
buf.as_mut_ptr().offset(9isize) as (*const c_void),
|
|
14usize,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_set_cccid(mut state: *mut ykpiv_state, mut ccc: *const Struct8) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut id: [u8; 14];
|
|
let mut buf: [u8; 51];
|
|
let mut len: usize = 0usize;
|
|
if state.is_null() {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
if ccc.is_null() {
|
|
if Enum7::PRNG_OK as (i32)
|
|
!= _ykpiv_prng_generate(id.as_mut_ptr(), mem::size_of::<[u8; 14]>()) as (i32)
|
|
{
|
|
return ErrorKind::YKPIV_RANDOMNESS_ERROR;
|
|
}
|
|
} else {
|
|
memcpy(
|
|
id.as_mut_ptr() as (*mut c_void),
|
|
(*ccc).data.as_mut_ptr() as (*const c_void),
|
|
mem::size_of::<[u8; 14]>(),
|
|
);
|
|
}
|
|
(if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
len = 51usize;
|
|
memcpy(
|
|
buf.as_mut_ptr() as (*mut c_void),
|
|
CCC_TMPL as (*const c_void),
|
|
len,
|
|
);
|
|
memcpy(
|
|
buf.as_mut_ptr().offset(9isize) as (*mut c_void),
|
|
id.as_mut_ptr() as (*const 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 fn(*mut c_void, usize) -> *mut c_void,
|
|
pub pfn_realloc: unsafe fn(*mut c_void, *mut c_void, usize) -> *mut c_void,
|
|
pub pfn_free: unsafe fn(*mut c_void, *mut c_void),
|
|
pub alloc_data: *mut 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
|
|
}
|
|
}
|
|
|
|
pub 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
|
|
}
|
|
}
|
|
|
|
pub 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,
|
|
) -> ErrorKind {
|
|
let mut _currentBlock;
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut pKey: *mut _ykpiv_key = 0i32 as (*mut c_void) as (*mut _ykpiv_key);
|
|
let mut pData: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut pTemp: *mut u8 = 0i32 as (*mut 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 c_void) as (*mut *mut _ykpiv_key) == data
|
|
|| 0i32 as (*mut c_void) as (*mut usize) == data_len
|
|
|| 0i32 as (*mut c_void) as (*mut u8) == key_count
|
|
{
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
*key_count = 0u8;
|
|
*data = 0i32 as (*mut c_void) as (*mut _ykpiv_key);
|
|
*data_len = 0usize;
|
|
if 0i32 as (*mut c_void) as (*mut u8) == {
|
|
pData = _ykpiv_alloc(state, CB_PAGE) as (*mut u8);
|
|
pData
|
|
} {
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else {
|
|
cbData = CB_PAGE;
|
|
i = 0usize;
|
|
'loop5: loop {
|
|
if !(i < mem::size_of::<*const u8>()) {
|
|
_currentBlock = 6;
|
|
break;
|
|
}
|
|
cbBuf = 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) == ErrorKind::YKPIV_OK as (i32) && (cbBuf > 0usize) {
|
|
cbRealloc = if mem::size_of::<_ykpiv_key>()
|
|
.wrapping_add(cbBuf)
|
|
.wrapping_sub(1usize)
|
|
> cbData.wrapping_sub(offset)
|
|
{
|
|
(if mem::size_of::<_ykpiv_key>()
|
|
.wrapping_add(cbBuf)
|
|
.wrapping_sub(1usize)
|
|
.wrapping_sub(cbData.wrapping_sub(offset))
|
|
> CB_PAGE
|
|
{
|
|
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 c_void),
|
|
cbData.wrapping_add(cbRealloc),
|
|
) as (*mut u8);
|
|
pTemp
|
|
}
|
|
.is_null()
|
|
{
|
|
_currentBlock = 15;
|
|
break;
|
|
}
|
|
pData = pTemp;
|
|
pTemp = 0i32 as (*mut 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 c_void),
|
|
buf.as_mut_ptr() as (*const c_void),
|
|
cbBuf,
|
|
);
|
|
offset = offset.wrapping_add(
|
|
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 c_void) as (*mut u8);
|
|
if !data_len.is_null() {
|
|
*data_len = offset;
|
|
}
|
|
res = ErrorKind::YKPIV_OK;
|
|
} else {
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
}
|
|
}
|
|
}
|
|
if !pData.is_null() {
|
|
_ykpiv_free(state, pData as (*mut c_void));
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_free(mut _state: *mut ykpiv_state, mut data: *mut c_void) -> ErrorKind {
|
|
if !data.is_null() {
|
|
free(data);
|
|
}
|
|
|
|
ErrorKind::YKPIV_OK
|
|
}
|
|
|
|
pub fn ykpiv_util_read_cert(
|
|
mut state: *mut ykpiv_state,
|
|
mut slot: u8,
|
|
mut data: *mut *mut u8,
|
|
mut data_len: *mut usize,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut buf: [u8; 3072];
|
|
let mut cbBuf: usize = mem::size_of::<[u8; 3072]>();
|
|
if 0i32 as (*mut c_void) as (*mut *mut u8) == data
|
|
|| 0i32 as (*mut c_void) as (*mut usize) == data_len
|
|
{
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
*data = 0i32 as (*mut u8);
|
|
*data_len = 0usize;
|
|
if ErrorKind::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 c_void) as (*mut u8);
|
|
*data_len = 0usize;
|
|
} else if {
|
|
*data = _ykpiv_alloc(state, cbBuf) as (*mut u8);
|
|
*data
|
|
}
|
|
.is_null()
|
|
{
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else {
|
|
memcpy(
|
|
*data as (*mut c_void),
|
|
buf.as_mut_ptr() as (*const c_void),
|
|
cbBuf,
|
|
);
|
|
*data_len = cbBuf;
|
|
}
|
|
}
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_write_cert(
|
|
mut state: *mut ykpiv_state,
|
|
mut slot: u8,
|
|
mut data: *mut u8,
|
|
mut data_len: usize,
|
|
mut certinfo: u8,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::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
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_delete_cert(mut state: *mut ykpiv_state, mut slot: u8) -> ErrorKind {
|
|
ykpiv_util_write_cert(state, slot, 0i32 as (*mut c_void) as (*mut u8), 0usize, 0u8)
|
|
}
|
|
|
|
pub fn ykpiv_util_block_puk(mut state: *mut ykpiv_state) -> ErrorKind {
|
|
let mut _currentBlock;
|
|
let mut res: ErrorKind = ErrorKind::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 = mem::size_of::<[u8; 3072]>();
|
|
let mut p_item: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_item: usize = 0usize;
|
|
let mut flags: u8 = 0u8;
|
|
if 0i32 as (*mut c_void) as (*mut ykpiv_state) == state {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if ErrorKind::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 ErrorKind::YKPIV_OK as (i32) == {
|
|
res = ykpiv_change_puk(
|
|
state,
|
|
puk as (*const u8),
|
|
mem::size_of::<*mut u8>(),
|
|
puk as (*const u8),
|
|
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 !(ErrorKind::YKPIV_PIN_LOCKED as (i32) == res as (i32)) {
|
|
_currentBlock = 3;
|
|
continue;
|
|
}
|
|
tries = 0i32;
|
|
res = ErrorKind::YKPIV_OK;
|
|
_currentBlock = 3;
|
|
}
|
|
} else {
|
|
if ErrorKind::YKPIV_OK as (i32)
|
|
== _read_metadata(
|
|
state,
|
|
0x80u8,
|
|
data.as_mut_ptr(),
|
|
&mut cb_data as (*mut usize),
|
|
) as (i32)
|
|
{
|
|
if ErrorKind::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 mem::size_of::<u8>() == cb_item {
|
|
memcpy(
|
|
&mut flags as (*mut u8) as (*mut c_void),
|
|
p_item as (*const c_void),
|
|
cb_item,
|
|
);
|
|
} else if (*state).verbose != 0 {
|
|
eprintln!(
|
|
"admin flags exist, but are incorrect size = {}",
|
|
cb_item,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
flags = (flags as (i32) | 0x1i32) as (u8);
|
|
if ErrorKind::YKPIV_OK as (i32)
|
|
!= _set_metadata_item(
|
|
data.as_mut_ptr(),
|
|
&mut cb_data as (*mut usize),
|
|
3063usize,
|
|
0x81u8,
|
|
&mut flags as (*mut u8),
|
|
mem::size_of::<u8>(),
|
|
) as (i32)
|
|
{
|
|
if (*state).verbose == 0 {
|
|
_currentBlock = 20;
|
|
continue;
|
|
}
|
|
eprintln!("could not set admin flags");
|
|
_currentBlock = 20;
|
|
} else {
|
|
if !(ErrorKind::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;
|
|
}
|
|
eprintln!("could not write admin metadata");
|
|
_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
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_read_mscmap(
|
|
mut state: *mut ykpiv_state,
|
|
mut containers: *mut *mut _ykpiv_container,
|
|
mut n_containers: *mut usize,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut buf: [u8; 3072];
|
|
let mut cbBuf: usize = mem::size_of::<[u8; 3072]>();
|
|
let mut len: usize = 0usize;
|
|
let mut ptr: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
if 0i32 as (*mut c_void) as (*mut *mut _ykpiv_container) == containers
|
|
|| 0i32 as (*mut c_void) as (*mut usize) == n_containers
|
|
{
|
|
res = ErrorKind::YKPIV_GENERIC_ERROR;
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
return ErrorKind::YKPIV_PCSC_ERROR;
|
|
} else if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
*containers = 0i32 as (*mut _ykpiv_container);
|
|
*n_containers = 0usize;
|
|
if ErrorKind::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 = ErrorKind::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))
|
|
/ mem::size_of::<u8>() as (isize)) as (usize),
|
|
)
|
|
{
|
|
res = ErrorKind::YKPIV_OK;
|
|
} else if 0i32 as (*mut c_void) as (*mut _ykpiv_container) == {
|
|
*containers = _ykpiv_alloc(state, len) as (*mut _ykpiv_container);
|
|
*containers
|
|
} {
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else {
|
|
memcpy(*containers as (*mut c_void), ptr as (*const c_void), len);
|
|
*n_containers = len.wrapping_div(mem::size_of::<_ykpiv_container>());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
|
|
unsafe fn _obj_size_max(mut state: *mut ykpiv_state) -> usize {
|
|
(if !state.is_null() && (*state).isNEO {
|
|
2048i32 - 9i32
|
|
} else {
|
|
3063i32
|
|
}) as (usize)
|
|
}
|
|
|
|
pub fn ykpiv_util_write_mscmap(
|
|
mut state: *mut ykpiv_state,
|
|
mut containers: *mut _ykpiv_container,
|
|
mut n_containers: usize,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::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(mem::size_of::<_ykpiv_container>());
|
|
if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
if 0i32 as (*mut c_void) as (*mut _ykpiv_container) == containers
|
|
|| 0usize == n_containers
|
|
{
|
|
if 0i32 as (*mut c_void) as (*mut _ykpiv_container) != containers
|
|
|| 0usize != n_containers
|
|
{
|
|
res = ErrorKind::YKPIV_GENERIC_ERROR;
|
|
} else {
|
|
res = _ykpiv_save_object(
|
|
state,
|
|
0x5fff10i32,
|
|
0i32 as (*mut 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 = ErrorKind::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 c_void),
|
|
containers as (*mut u8) as (*const 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
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_read_msroots(
|
|
mut state: *mut ykpiv_state,
|
|
mut data: *mut *mut u8,
|
|
mut data_len: *mut usize,
|
|
) -> ErrorKind {
|
|
let mut _currentBlock;
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut buf: [u8; 3072];
|
|
let mut cbBuf: usize = mem::size_of::<[u8; 3072]>();
|
|
let mut len: usize = 0usize;
|
|
let mut ptr: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut object_id: i32 = 0i32;
|
|
let mut tag: u8 = 0u8;
|
|
let mut pData: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut pTemp: *mut u8 = 0i32 as (*mut 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() {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::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 c_void) as (*mut u8) == {
|
|
pData = _ykpiv_alloc(state, cbData) as (*mut u8);
|
|
pData
|
|
} {
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else {
|
|
object_id = 0x5fff11i32;
|
|
'loop5: loop {
|
|
if !(object_id <= 0x5fff15i32) {
|
|
_currentBlock = 15;
|
|
break;
|
|
}
|
|
cbBuf = mem::size_of::<[u8; 3072]>();
|
|
if ErrorKind::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))
|
|
/ mem::size_of::<u8>() 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 c_void),
|
|
cbData.wrapping_add(cbRealloc),
|
|
) as (*mut u8);
|
|
pTemp
|
|
}
|
|
.is_null()
|
|
{
|
|
_currentBlock = 16;
|
|
break;
|
|
}
|
|
pData = pTemp;
|
|
pTemp = 0i32 as (*mut c_void) as (*mut u8);
|
|
}
|
|
cbData = cbData.wrapping_add(cbRealloc);
|
|
memcpy(
|
|
pData.offset(offset as (isize)) as (*mut c_void),
|
|
ptr as (*const 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 c_void) as (*mut u8);
|
|
*data_len = offset;
|
|
res = ErrorKind::YKPIV_OK;
|
|
} else if _currentBlock == 16 {
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else if _currentBlock == 17 {
|
|
res = ErrorKind::YKPIV_OK;
|
|
} else if _currentBlock == 18 {
|
|
res = ErrorKind::YKPIV_OK;
|
|
} else {
|
|
res = ErrorKind::YKPIV_OK;
|
|
}
|
|
}
|
|
}
|
|
if !pData.is_null() {
|
|
_ykpiv_free(state, pData as (*mut c_void));
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_write_msroots(
|
|
mut state: *mut ykpiv_state,
|
|
mut data: *mut u8,
|
|
mut data_len: usize,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::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 ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
if 0i32 as (*mut c_void) as (*mut u8) == data || 0usize == data_len {
|
|
if 0i32 as (*mut c_void) as (*mut u8) != data || 0usize != data_len {
|
|
res = ErrorKind::YKPIV_GENERIC_ERROR;
|
|
} else {
|
|
res = _ykpiv_save_object(
|
|
state,
|
|
0x5fff11i32,
|
|
0i32 as (*mut 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 = ErrorKind::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 c_void),
|
|
data.offset(data_offset as (isize)) as (*const 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 ErrorKind::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
|
|
}
|
|
}
|
|
|
|
pub unsafe 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,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::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 = mem::size_of::<[u8; 1024]>();
|
|
let mut sw: i32;
|
|
let mut ptr_modulus: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_modulus: usize = 0usize;
|
|
let mut ptr_exp: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_exp: usize = 0usize;
|
|
let mut ptr_point: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_point: usize = 0usize;
|
|
let mut setting_roca = SettingBool {
|
|
value: false,
|
|
source: SettingSource::SETTING_SOURCE_DEFAULT,
|
|
};
|
|
let sz_setting_roca: &str = "Enable_Unsafe_Keygen_ROCA";
|
|
let sz_roca_allow_user: &str =
|
|
"was permitted by an end-user configuration setting, but is not recommended.";
|
|
let sz_roca_allow_admin: &str =
|
|
"was permitted by an administrator configuration setting, but is not recommended.";
|
|
let sz_roca_block_user: &str = "was blocked due to an end-user configuration setting.";
|
|
let sz_roca_block_admin: &str = "was blocked due to an administrator configuration setting.";
|
|
let sz_roca_default: &str = "was permitted by default, but is not recommended. The default behavior will change in a future Yubico release.";
|
|
|
|
if state.is_null() {
|
|
ErrorKind::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 setting_name = CString::new(sz_setting_roca).unwrap();
|
|
setting_roca = setting_get_bool(setting_name.as_ptr(), true);
|
|
let switch9 = setting_roca.source;
|
|
|
|
let psz_msg = if switch9 as (i32) == SettingSource::SETTING_SOURCE_USER as (i32) {
|
|
if setting_roca.value {
|
|
sz_roca_allow_user
|
|
} else {
|
|
sz_roca_block_user
|
|
}
|
|
} else if switch9 as (i32) == SettingSource::SETTING_SOURCE_ADMIN as (i32) {
|
|
if setting_roca.value {
|
|
sz_roca_allow_admin
|
|
} else {
|
|
sz_roca_block_admin
|
|
}
|
|
} else {
|
|
sz_roca_default
|
|
};
|
|
|
|
eprintln!(
|
|
"YubiKey serial number {} is affected by vulnerability CVE-2017-15361 \
|
|
(ROCA) and should be replaced. On-chip key generation {} See \
|
|
YSA-2017-01 <https://www.yubico.com/support/security-advisories/ysa-2017-01/> \
|
|
for additional information on device replacement and mitigation assistance",
|
|
(*state).serial,
|
|
psz_msg
|
|
);
|
|
|
|
if !setting_roca.value {
|
|
return ErrorKind::YKPIV_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
}
|
|
if algorithm as (i32) == 0x14i32 || algorithm as (i32) == 0x11i32 {
|
|
if point.is_null() || point_len.is_null() {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Invalid output parameter for ECC algorithm",);
|
|
}
|
|
return ErrorKind::YKPIV_GENERIC_ERROR;
|
|
} else {
|
|
*point = 0i32 as (*mut 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 {
|
|
eprintln!("Invalid output parameter for RSA algorithm",);
|
|
}
|
|
return ErrorKind::YKPIV_GENERIC_ERROR;
|
|
} else {
|
|
*modulus = 0i32 as (*mut c_void) as (*mut u8);
|
|
*modulus_len = 0usize;
|
|
*exp = 0i32 as (*mut c_void) as (*mut u8);
|
|
*exp_len = 0usize;
|
|
}
|
|
} else {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Invalid algorithm specified");
|
|
}
|
|
return ErrorKind::YKPIV_GENERIC_ERROR;
|
|
}
|
|
(if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::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 = ErrorKind::YKPIV_ALGORITHM_ERROR;
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Unexpected algorithm.\n");
|
|
}
|
|
} 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 ErrorKind::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))
|
|
/ mem::size_of::<u8>() as (isize),
|
|
data.as_mut_ptr(),
|
|
&mut recv_len as (*mut usize),
|
|
&mut sw as (*mut i32),
|
|
);
|
|
res
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Failed to communicate.\n");
|
|
}
|
|
} else if sw != 0x9000i32 {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Failed to generate new key (");
|
|
}
|
|
if sw == 0x6b00i32 {
|
|
res = ErrorKind::YKPIV_KEY_ERROR;
|
|
if (*state).verbose != 0 {
|
|
eprintln!("incorrect slot)\n");
|
|
}
|
|
} else if sw == 0x6a80i32 {
|
|
res = ErrorKind::YKPIV_ALGORITHM_ERROR;
|
|
if (*state).verbose != 0 {
|
|
if pin_policy as (i32) != 0i32 {
|
|
eprintln!("pin policy not supported?)\n",);
|
|
} else if touch_policy as (i32) != 0i32 {
|
|
eprintln!("touch policy not supported?)\n",);
|
|
} else {
|
|
eprintln!("algorithm not supported?)\n",);
|
|
}
|
|
}
|
|
} else if sw == 0x6982i32 {
|
|
res = ErrorKind::YKPIV_AUTHENTICATION_ERROR;
|
|
if (*state).verbose != 0 {
|
|
eprintln!("not authenticated)");
|
|
}
|
|
} else {
|
|
res = ErrorKind::YKPIV_GENERIC_ERROR;
|
|
if (*state).verbose != 0 {
|
|
eprintln!("error {:x})", 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 {
|
|
eprintln!("Failed to parse public key structure (modulus).");
|
|
}
|
|
res = ErrorKind::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 c_void) as (*mut u8) == {
|
|
ptr_modulus = _ykpiv_alloc(state, cb_modulus) as (*mut u8);
|
|
ptr_modulus
|
|
} {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Failed to allocate memory for modulus.");
|
|
}
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else {
|
|
memcpy(
|
|
ptr_modulus as (*mut c_void),
|
|
data_ptr as (*const c_void),
|
|
cb_modulus,
|
|
);
|
|
data_ptr = data_ptr.offset(len as (isize));
|
|
if *data_ptr as (i32) != 0x82i32 {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Failed to parse public key structure (public exponent).");
|
|
}
|
|
res = ErrorKind::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 c_void) as (*mut u8) == {
|
|
ptr_exp = _ykpiv_alloc(state, cb_exp) as (*mut u8);
|
|
ptr_exp
|
|
} {
|
|
if (*state).verbose != 0 {
|
|
eprintln!(
|
|
"Failed to allocate memory for public exponent."
|
|
);
|
|
}
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else {
|
|
memcpy(
|
|
ptr_exp as (*mut c_void),
|
|
data_ptr as (*const c_void),
|
|
cb_exp,
|
|
);
|
|
*modulus = ptr_modulus;
|
|
ptr_modulus = 0i32 as (*mut c_void) as (*mut u8);
|
|
*modulus_len = cb_modulus;
|
|
*exp = ptr_exp;
|
|
ptr_exp = 0i32 as (*mut 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 {
|
|
eprintln!("Failed to parse public key structure.\n",);
|
|
}
|
|
res = ErrorKind::YKPIV_PARSE_ERROR;
|
|
} else if *{
|
|
let _old = data_ptr;
|
|
data_ptr = data_ptr.offset(1isize);
|
|
_old
|
|
} as (usize)
|
|
!= len
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Unexpected length.\n");
|
|
}
|
|
res = ErrorKind::YKPIV_ALGORITHM_ERROR;
|
|
} else {
|
|
cb_point = len;
|
|
if 0i32 as (*mut c_void) as (*mut u8) == {
|
|
ptr_point = _ykpiv_alloc(state, cb_point) as (*mut u8);
|
|
ptr_point
|
|
} {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Failed to allocate memory for public point.");
|
|
}
|
|
res = ErrorKind::YKPIV_MEMORY_ERROR;
|
|
} else {
|
|
memcpy(
|
|
ptr_point as (*mut c_void),
|
|
data_ptr as (*const c_void),
|
|
cb_point,
|
|
);
|
|
*point = ptr_point;
|
|
ptr_point = 0i32 as (*mut c_void) as (*mut u8);
|
|
*point_len = cb_point;
|
|
}
|
|
}
|
|
} else {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("Wrong algorithm.");
|
|
}
|
|
res = ErrorKind::YKPIV_ALGORITHM_ERROR;
|
|
}
|
|
}
|
|
}
|
|
if !ptr_modulus.is_null() {
|
|
_ykpiv_free(state, modulus as (*mut c_void));
|
|
}
|
|
if !ptr_exp.is_null() {
|
|
_ykpiv_free(state, ptr_exp as (*mut c_void));
|
|
}
|
|
if !ptr_point.is_null() {
|
|
_ykpiv_free(state, ptr_exp as (*mut c_void));
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
#[repr(i32)]
|
|
#[allow(non_camel_case_types)]
|
|
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
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_get_config(
|
|
mut state: *mut ykpiv_state,
|
|
mut config: *mut _ykpiv_config,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut data = [0u8; 3072];
|
|
let mut cb_data: usize = mem::size_of::<[u8; 3072]>();
|
|
let mut p_item: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_item: usize = 0usize;
|
|
if 0i32 as (*mut c_void) as (*mut ykpiv_state) == state {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if 0i32 as (*mut c_void) as (*mut _ykpiv_config) == config {
|
|
ErrorKind::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 ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
if ErrorKind::YKPIV_OK as (i32)
|
|
== _read_metadata(
|
|
state,
|
|
0x80u8,
|
|
data.as_mut_ptr(),
|
|
&mut cb_data as (*mut usize),
|
|
) as (i32)
|
|
{
|
|
if ErrorKind::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 ErrorKind::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 {
|
|
eprintln!("conflicting types of mgm key administration configured");
|
|
}
|
|
} else {
|
|
(*config).mgm_type = Enum10::YKPIV_CONFIG_MGM_DERIVED;
|
|
}
|
|
}
|
|
if ErrorKind::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 {
|
|
eprintln!("pin timestamp in admin metadata is an invalid size");
|
|
}
|
|
} else {
|
|
memcpy(
|
|
&mut (*config).pin_last_changed as (*mut u32) as (*mut c_void),
|
|
p_item as (*const c_void),
|
|
cb_item,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
cb_data = mem::size_of::<[u8; 3072]>();
|
|
if ErrorKind::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 ErrorKind::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 ErrorKind::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 {
|
|
eprintln!(
|
|
"conflicting types of mgm key administration configured - protected mgm exists"
|
|
);
|
|
}
|
|
}
|
|
(*config).mgm_type = Enum10::YKPIV_CONFIG_MGM_PROTECTED;
|
|
}
|
|
}
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
})
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_set_pin_last_changed(mut state: *mut ykpiv_state) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut ykrc: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut data = [0u8; 3072];
|
|
let mut cb_data: usize = mem::size_of::<[u8; 3072]>();
|
|
let mut tnow: time_t = 0;
|
|
if 0i32 as (*mut c_void) as (*mut ykpiv_state) == state {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
if ErrorKind::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(0 as *mut time_t);
|
|
if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _set_metadata_item(
|
|
data.as_mut_ptr(),
|
|
&mut cb_data as (*mut usize),
|
|
3063usize,
|
|
0x83u8,
|
|
mem::transmute(&mut tnow),
|
|
4usize,
|
|
);
|
|
res
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not set pin timestamp, err = {}\n", res as (i32),);
|
|
}
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _write_metadata(state, 0x80u8, data.as_mut_ptr(), cb_data);
|
|
res
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not write admin data, err = {}", 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,
|
|
}
|
|
|
|
pub fn ykpiv_util_get_derived_mgm(
|
|
mut state: *mut ykpiv_state,
|
|
mut pin: *const u8,
|
|
pin_len: usize,
|
|
mut mgm: *mut _ykpiv_mgm,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut p5rc: Enum11 = Enum11::PKCS5_OK;
|
|
let mut data = [0u8; 3072];
|
|
let mut cb_data: usize = mem::size_of::<[u8; 3072]>();
|
|
let mut p_item: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_item: usize = 0usize;
|
|
if 0i32 as (*mut c_void) as (*mut ykpiv_state) == state {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if 0i32 as (*mut c_void) as (*const u8) == pin
|
|
|| 0usize == pin_len
|
|
|| 0i32 as (*mut c_void) as (*mut _ykpiv_mgm) == mgm
|
|
{
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
if ErrorKind::YKPIV_OK as (i32) == {
|
|
res = _read_metadata(
|
|
state,
|
|
0x80u8,
|
|
data.as_mut_ptr(),
|
|
&mut cb_data as (*mut usize),
|
|
);
|
|
res
|
|
} as (i32)
|
|
{
|
|
if ErrorKind::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 {
|
|
eprintln!(
|
|
"derived mgm salt exists, but is incorrect size = {}",
|
|
cb_item,
|
|
);
|
|
}
|
|
res = ErrorKind::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),
|
|
mem::size_of::<[u8; 24]>(),
|
|
);
|
|
p5rc
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("pbkdf2 failure, err = {}", p5rc as (i32));
|
|
}
|
|
res = ErrorKind::YKPIV_GENERIC_ERROR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_get_protected_mgm(
|
|
mut state: *mut ykpiv_state,
|
|
mut mgm: *mut _ykpiv_mgm,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut data = [0u8; 3072];
|
|
let mut cb_data: usize = mem::size_of::<[u8; 3072]>();
|
|
let mut p_item: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_item: usize = 0usize;
|
|
if 0i32 as (*mut c_void) as (*mut ykpiv_state) == state {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if 0i32 as (*mut c_void) as (*mut _ykpiv_mgm) == mgm {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
ErrorKind::YKPIV_PCSC_ERROR
|
|
} else {
|
|
if !(ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_ensure_application_selected(state);
|
|
res
|
|
} as (i32))
|
|
{
|
|
if ErrorKind::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 {
|
|
eprintln!("could not read protected data, err = {}", res as (i32),);
|
|
}
|
|
} else if ErrorKind::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 {
|
|
eprintln!(
|
|
"could not read protected mgm from metadata, err = {}",
|
|
res as (i32),
|
|
);
|
|
}
|
|
} else if cb_item != mem::size_of::<[u8; 24]>() {
|
|
if (*state).verbose != 0 {
|
|
eprintln!(
|
|
"protected data contains mgm, but is the wrong size = {}",
|
|
cb_item,
|
|
);
|
|
}
|
|
res = ErrorKind::YKPIV_AUTHENTICATION_ERROR;
|
|
} else {
|
|
memcpy(
|
|
(*mgm).data.as_mut_ptr() as (*mut c_void),
|
|
p_item as (*const c_void),
|
|
cb_item,
|
|
);
|
|
}
|
|
}
|
|
memset_s(
|
|
data.as_mut_ptr() as (*mut c_void),
|
|
mem::size_of::<[u8; 3072]>(),
|
|
0i32,
|
|
mem::size_of::<[u8; 3072]>(),
|
|
);
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_set_protected_mgm(
|
|
mut state: *mut ykpiv_state,
|
|
mut mgm: *mut _ykpiv_mgm,
|
|
) -> ErrorKind {
|
|
let mut _currentBlock;
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut ykrc: ErrorKind = ErrorKind::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 = [0u8; 3072];
|
|
let mut cb_data: usize = mem::size_of::<[u8; 3072]>();
|
|
let mut p_item: *mut u8 = 0i32 as (*mut c_void) as (*mut u8);
|
|
let mut cb_item: usize = 0usize;
|
|
let mut flags_1: u8 = 0u8;
|
|
if 0i32 as (*mut c_void) as (*mut ykpiv_state) == state {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
if mgm.is_null() {
|
|
fGenerate = true;
|
|
} else {
|
|
fGenerate = true;
|
|
memcpy(
|
|
mgm_key.as_mut_ptr() as (*mut c_void),
|
|
(*mgm).data.as_mut_ptr() as (*const c_void),
|
|
mem::size_of::<[u8; 24]>(),
|
|
);
|
|
i = 0usize;
|
|
'loop3: loop {
|
|
if !(i < 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 ErrorKind::YKPIV_OK as (i32) != {
|
|
res = _ykpiv_begin_transaction(state);
|
|
res
|
|
} as (i32)
|
|
{
|
|
res = ErrorKind::YKPIV_PCSC_ERROR;
|
|
} else if !(ErrorKind::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(), mem::size_of::<[u8; 24]>());
|
|
prngrc
|
|
} as (i32)
|
|
{
|
|
_currentBlock = 47;
|
|
break;
|
|
}
|
|
}
|
|
if ErrorKind::YKPIV_OK as (i32) != {
|
|
ykrc = ykpiv_set_mgmkey(state, mgm_key.as_mut_ptr() as (*const u8));
|
|
ykrc
|
|
} as (i32)
|
|
{
|
|
if ErrorKind::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 c_void),
|
|
mgm_key.as_mut_ptr() as (*const c_void),
|
|
mem::size_of::<[u8; 24]>(),
|
|
);
|
|
}
|
|
if ErrorKind::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 ErrorKind::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(),
|
|
mem::size_of::<[u8; 24]>(),
|
|
);
|
|
ykrc
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not set protected mgm item, err = {}", ykrc as (i32),);
|
|
_currentBlock = 26;
|
|
} else {
|
|
_currentBlock = 26;
|
|
}
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
ykrc = _write_metadata(state, 0x88u8, data.as_mut_ptr(), cb_data);
|
|
ykrc
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not write protected data, err = {}", ykrc as (i32),);
|
|
_currentBlock = 51;
|
|
} else {
|
|
_currentBlock = 51;
|
|
}
|
|
} else {
|
|
_currentBlock = 26;
|
|
}
|
|
if _currentBlock == 51 {
|
|
} else {
|
|
cb_data = mem::size_of::<[u8; 3072]>();
|
|
if ErrorKind::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 ErrorKind::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 {
|
|
eprintln!("admin data exists, but flags are not present",);
|
|
}
|
|
}
|
|
if cb_item == mem::size_of::<u8>() {
|
|
memcpy(
|
|
&mut flags_1 as (*mut u8) as (*mut c_void),
|
|
p_item as (*const c_void),
|
|
cb_item,
|
|
);
|
|
} else if (*state).verbose != 0 {
|
|
eprintln!("admin data flags are an incorrect size = {}", cb_item,);
|
|
}
|
|
if ErrorKind::YKPIV_OK as (i32) != {
|
|
ykrc = _set_metadata_item(
|
|
data.as_mut_ptr(),
|
|
&mut cb_data as (*mut usize),
|
|
3063usize,
|
|
0x82u8,
|
|
0i32 as (*mut c_void) as (*mut u8),
|
|
0usize,
|
|
);
|
|
ykrc
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!(
|
|
"could not unset derived mgm salt, err = {}",
|
|
ykrc as (i32),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
flags_1 = (flags_1 as (i32) | 0x2i32) as (u8);
|
|
if ErrorKind::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),
|
|
mem::size_of::<u8>(),
|
|
);
|
|
ykrc
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not set admin flags item, err = {}", ykrc as (i32),);
|
|
}
|
|
} else if ErrorKind::YKPIV_OK as (i32) != {
|
|
ykrc = _write_metadata(state, 0x80u8, data.as_mut_ptr(), cb_data);
|
|
ykrc
|
|
} as (i32)
|
|
{
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not write admin data, err = {}", ykrc as (i32),);
|
|
}
|
|
}
|
|
}
|
|
} else if _currentBlock == 44 {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not set new derived mgm key, err = {}", ykrc as (i32),);
|
|
}
|
|
res = ykrc;
|
|
} else {
|
|
if (*state).verbose != 0 {
|
|
eprintln!("could not generate new mgm, err = {}", prngrc as (i32),);
|
|
}
|
|
res = ErrorKind::YKPIV_RANDOMNESS_ERROR;
|
|
}
|
|
}
|
|
memset_s(
|
|
data.as_mut_ptr() as (*mut c_void),
|
|
mem::size_of::<[u8; 3072]>(),
|
|
0i32,
|
|
mem::size_of::<[u8; 3072]>(),
|
|
);
|
|
memset_s(
|
|
mgm_key.as_mut_ptr() as (*mut c_void),
|
|
mem::size_of::<[u8; 24]>(),
|
|
0i32,
|
|
mem::size_of::<[u8; 24]>(),
|
|
);
|
|
_ykpiv_end_transaction(state);
|
|
res
|
|
}
|
|
}
|
|
|
|
pub fn ykpiv_util_reset(mut state: *mut ykpiv_state) -> ErrorKind {
|
|
let mut templ: *mut u8 = 0i32 as (*mut u8);
|
|
let mut data: [u8; 255];
|
|
let mut recv_len: usize = mem::size_of::<[u8; 255]>();
|
|
let mut res: ErrorKind;
|
|
let mut sw: i32;
|
|
res = ykpiv_transfer_data(
|
|
state,
|
|
templ as (*const u8),
|
|
0i32 as (*mut c_void) as (*const u8),
|
|
0isize,
|
|
data.as_mut_ptr(),
|
|
&mut recv_len as (*mut usize),
|
|
&mut sw as (*mut i32),
|
|
);
|
|
if ErrorKind::YKPIV_OK as (i32) == res as (i32) && (0x9000i32 == sw) {
|
|
ErrorKind::YKPIV_OK
|
|
} else {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
}
|
|
}
|
|
|
|
pub 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 fn _read_certificate(
|
|
mut state: *mut ykpiv_state,
|
|
mut slot: u8,
|
|
mut buf: *mut u8,
|
|
mut buf_len: *mut usize,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut ptr: *mut u8 = 0i32 as (*mut 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 {
|
|
ErrorKind::YKPIV_INVALID_OBJECT
|
|
} else {
|
|
if ErrorKind::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 ErrorKind::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))
|
|
/ mem::size_of::<u8>() as (isize)) as (usize),
|
|
)
|
|
{
|
|
*buf_len = 0usize;
|
|
return ErrorKind::YKPIV_OK;
|
|
} else {
|
|
memmove(buf as (*mut c_void), ptr as (*const c_void), len);
|
|
*buf_len = len;
|
|
}
|
|
}
|
|
} else {
|
|
*buf_len = 0usize;
|
|
}
|
|
res
|
|
}
|
|
}
|
|
|
|
unsafe fn _write_certificate(
|
|
mut state: *mut ykpiv_state,
|
|
mut slot: u8,
|
|
mut data: *mut u8,
|
|
mut data_len: usize,
|
|
mut certinfo: u8,
|
|
) -> ErrorKind {
|
|
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 {
|
|
ErrorKind::YKPIV_INVALID_OBJECT
|
|
} else if 0i32 as (*mut c_void) as (*mut u8) == data || 0usize == data_len {
|
|
(if 0i32 as (*mut c_void) as (*mut u8) != data || 0usize != data_len {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
_ykpiv_save_object(state, object_id, 0i32 as (*mut 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 {
|
|
ErrorKind::YKPIV_SIZE_ERROR
|
|
} else if req_len > _obj_size_max(state) {
|
|
ErrorKind::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 c_void),
|
|
data as (*const 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 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,
|
|
) -> ErrorKind {
|
|
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() {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
*pp_item = 0i32 as (*mut 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))
|
|
/ mem::size_of::<u8>() 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;
|
|
ErrorKind::YKPIV_OK
|
|
} else {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
})
|
|
} else {
|
|
ErrorKind::YKPIV_SIZE_ERROR
|
|
})
|
|
}
|
|
}
|
|
|
|
unsafe fn _get_length_size(mut length: usize) -> i32 {
|
|
if length < 0x80usize {
|
|
1i32
|
|
} else if length < 0xffusize {
|
|
2i32
|
|
} else {
|
|
3i32
|
|
}
|
|
}
|
|
|
|
unsafe 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,
|
|
) -> ErrorKind {
|
|
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 c_void) as (*mut u8);
|
|
let mut cb_moved: isize = 0isize;
|
|
if data.is_null() || pcb_data.is_null() {
|
|
ErrorKind::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 {
|
|
ErrorKind::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 {
|
|
ErrorKind::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 c_void), p_item as (*const c_void), cb_item);
|
|
*pcb_data =
|
|
(*pcb_data).wrapping_add(1usize.wrapping_add(cb_len).wrapping_add(cb_item));
|
|
ErrorKind::YKPIV_OK
|
|
})
|
|
})
|
|
} else if cb_temp == cb_item {
|
|
memcpy(p_temp as (*mut c_void), p_item as (*const c_void), cb_item);
|
|
ErrorKind::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 {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
memmove(
|
|
p_next.offset(cb_moved) as (*mut c_void),
|
|
p_next as (*const c_void),
|
|
(*pcb_data).wrapping_sub(
|
|
((p_next as (isize)).wrapping_sub(data as (isize))
|
|
/ mem::size_of::<u8>() 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 c_void), p_item as (*const c_void), cb_item);
|
|
}
|
|
ErrorKind::YKPIV_OK
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
unsafe fn _read_metadata(
|
|
mut state: *mut ykpiv_state,
|
|
mut tag: u8,
|
|
mut data: *mut u8,
|
|
mut pcb_data: *mut usize,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut p_temp: *mut u8 = 0i32 as (*mut 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 {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
if tag as (i32) == 0x88i32 {
|
|
obj_id = 0x5fc109i32;
|
|
} else if tag as (i32) == 0x80i32 {
|
|
obj_id = 0x5fff00i32;
|
|
} else {
|
|
return ErrorKind::YKPIV_INVALID_OBJECT;
|
|
}
|
|
cb_temp = *pcb_data;
|
|
*pcb_data = 0usize;
|
|
(if ErrorKind::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 {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
p_temp = data;
|
|
(if tag as (i32)
|
|
!= *{
|
|
let _old = p_temp;
|
|
p_temp = p_temp.offset(1isize);
|
|
_old
|
|
} as (i32)
|
|
{
|
|
ErrorKind::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))
|
|
/ mem::size_of::<u8>() as (isize)) as (usize),
|
|
)
|
|
{
|
|
*pcb_data = 0usize;
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
memmove(data as (*mut c_void), p_temp as (*const c_void), *pcb_data);
|
|
ErrorKind::YKPIV_OK
|
|
})
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
unsafe fn _write_metadata(
|
|
mut state: *mut ykpiv_state,
|
|
mut tag: u8,
|
|
mut data: *mut u8,
|
|
mut cb_data: usize,
|
|
) -> ErrorKind {
|
|
let mut res: ErrorKind = ErrorKind::YKPIV_OK;
|
|
let mut buf = [0u8; 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)) {
|
|
ErrorKind::YKPIV_GENERIC_ERROR
|
|
} else {
|
|
if tag as (i32) == 0x88i32 {
|
|
obj_id = 0x5fc109i32;
|
|
} else if tag as (i32) == 0x80i32 {
|
|
obj_id = 0x5fff00i32;
|
|
} else {
|
|
return ErrorKind::YKPIV_INVALID_OBJECT;
|
|
}
|
|
if data.is_null() || 0usize == cb_data {
|
|
res = _ykpiv_save_object(state, obj_id, 0i32 as (*mut 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 c_void), data as (*const 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))
|
|
/ mem::size_of::<u8>() as (isize)) as (usize),
|
|
);
|
|
}
|
|
res
|
|
}
|
|
}
|