pub unsafe fn ykpiv_import_private_key(
    state: *mut YubiKey,
    key: u8,
    algorithm: u8,
    p: *const u8,
    p_len: usize,
    q: *const u8,
    q_len: usize,
    dp: *const u8,
    dp_len: usize,
    dq: *const u8,
    dq_len: usize,
    qinv: *const u8,
    qinv_len: usize,
    ec_data: *const u8,
    ec_data_len: u8,
    pin_policy: u8,
    touch_policy: u8,
) -> ErrorKind {
    let mut key_data = [0u8; 1024];
    let mut in_ptr: *mut u8 = key_data.as_mut_ptr();
    let templ = [0, YKPIV_INS_IMPORT_KEY, algorithm, key];
    let mut data = [0u8; 256];
    let mut recv_len = data.len();
    let mut elem_len: u32 = 0;
    let mut sw: i32 = 0;
    let mut params: [*const u8; 5] = [ptr::null(); 5];
    let mut lens = [0usize; 5];
    let n_params: u8;
    let param_tag: i32;
    let mut res = ErrorKind::Ok;

    if state.is_null() {
        return ErrorKind::GenericError;
    }

    if key == YKPIV_KEY_CARDMGM
        || key < YKPIV_KEY_RETIRED1
        || key > YKPIV_KEY_RETIRED20 && (key < YKPIV_KEY_AUTHENTICATION)
        || key > YKPIV_KEY_CARDAUTH && (key != YKPIV_KEY_ATTESTATION)
    {
        return ErrorKind::KeyError;
    }

    if pin_policy != YKPIV_PINPOLICY_DEFAULT
        && (pin_policy != YKPIV_PINPOLICY_NEVER)
        && (pin_policy != YKPIV_PINPOLICY_ONCE)
        && (pin_policy != YKPIV_PINPOLICY_ALWAYS)
    {
        return ErrorKind::GenericError;
    }

    if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT
        && (touch_policy != YKPIV_TOUCHPOLICY_NEVER)
        && (touch_policy != YKPIV_TOUCHPOLICY_ALWAYS)
        && (touch_policy != YKPIV_TOUCHPOLICY_CACHED)
    {
        return ErrorKind::GenericError;
    }

    match algorithm {
        YKPIV_ALGO_RSA1024 | YKPIV_ALGO_RSA2048 => {
            if p_len + q_len + dp_len + dq_len + qinv_len >= 1024 {
                return ErrorKind::SizeError;
            } else {
                if algorithm == YKPIV_ALGO_RSA1024 {
                    elem_len = 64;
                }

                if algorithm == YKPIV_ALGO_RSA2048 {
                    elem_len = 128;
                }

                if p.is_null() || q.is_null() || dp.is_null() || dq.is_null() || qinv.is_null() {
                    return ErrorKind::GenericError;
                }

                params[0] = p;
                lens[0] = p_len;
                params[1] = q;
                lens[1] = q_len;
                params[2] = dp;
                lens[2] = dp_len;
                params[3] = dq;
                lens[3] = dq_len;
                params[4] = qinv;
                lens[4] = qinv_len;
                param_tag = 0x1;
                n_params = 5u8;
            }
        }
        YKPIV_ALGO_ECCP256 | YKPIV_ALGO_ECCP384 => {
            if ec_data_len as (usize) >= key_data.len() {
                return ErrorKind::SizeError;
            }

            if algorithm == YKPIV_ALGO_ECCP256 {
                elem_len = 32;
            } else if algorithm == YKPIV_ALGO_ECCP384 {
                elem_len = 48;
            }

            if ec_data.is_null() {
                return ErrorKind::GenericError;
            }

            params[0] = ec_data;
            lens[0] = ec_data_len as usize;
            param_tag = 0x6;
            n_params = 1;
        }
        _ => return ErrorKind::AlgorithmError,
    }

    for i in 0..n_params {
        *in_ptr = (param_tag + i as i32) as u8;
        in_ptr = in_ptr.offset(1);

        in_ptr = in_ptr.add(_ykpiv_set_length(in_ptr, elem_len as usize));
        let padding = (elem_len as (usize)).wrapping_sub(lens[i as usize]);
        let remaining = (key_data.as_mut_ptr() as usize) + 1024 - in_ptr as usize;

        if padding > remaining {
            return ErrorKind::AlgorithmError;
        }

        memset(in_ptr as *mut c_void, 0, padding);
        in_ptr = in_ptr.add(padding);
        memcpy(
            in_ptr as *mut c_void,
            params[i as usize] as *const c_void,
            lens[i as usize],
        );
        in_ptr = in_ptr.add(lens[i as usize]);
    }

    if pin_policy != YKPIV_PINPOLICY_DEFAULT {
        *in_ptr = YKPIV_PINPOLICY_TAG;
        *in_ptr.add(1) = 0x01;
        *in_ptr.add(2) = pin_policy;
        in_ptr = in_ptr.add(3);
    }

    if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT {
        *in_ptr = YKPIV_TOUCHPOLICY_TAG;
        *in_ptr.add(1) = 0x01;
        *in_ptr.add(2) = touch_policy;
        in_ptr = in_ptr.add(3);
    }

    if _ykpiv_begin_transaction(state) != ErrorKind::Ok {
        return ErrorKind::PcscError;
    } else if _ykpiv_ensure_application_selected(state) == ErrorKind::Ok {
        res = ykpiv_transfer_data(
            state,
            templ.as_ptr(),
            key_data.as_mut_ptr(),
            in_ptr as isize - key_data.as_mut_ptr() as isize,
            data.as_mut_ptr(),
            &mut recv_len,
            &mut sw,
        );

        if res == ErrorKind::Ok && sw != SW_SUCCESS {
            res = ErrorKind::GenericError;
            if sw == SW_ERR_SECURITY_STATUS {
                res = ErrorKind::AuthenticationError;
            }
        }
    }

    key_data.zeroize();
    _ykpiv_end_transaction(state);
    res
}
/// Import a private encryption or signing key into the YubiKey
Import a private encryption or signing key into the YubiKey
Import a private encryption or signing key into the YubiKey
pub unsafe fn ykpiv_import_private_key(
    state: *mut YubiKey,
    key: u8,
    algorithm: u8,
    p: *const u8,
    p_len: usize,
    q: *const u8,
    q_len: usize,
    dp: *const u8,
    dp_len: usize,
    dq: *const u8,
    dq_len: usize,
    qinv: *const u8,
    qinv_len: usize,
    ec_data: *const u8,
    ec_data_len: u8,
    pin_policy: u8,
    touch_policy: u8,
) -> ErrorKind {
    let mut key_data = [0u8; 1024];
    let mut in_ptr: *mut u8 = key_data.as_mut_ptr();
    let templ = [0, YKPIV_INS_IMPORT_KEY, algorithm, key];
    let mut data = [0u8; 256];
    let mut recv_len = data.len();
    let mut elem_len: u32 = 0;
    let mut sw: i32 = 0;
    let mut params: [*const u8; 5] = [ptr::null(); 5];
    let mut lens = [0usize; 5];
    let n_params: u8;
    let param_tag: i32;
    let mut res = ErrorKind::Ok;
    if state.is_null() {
        return ErrorKind::GenericError;
    }
    if key == YKPIV_KEY_CARDMGM
        || key < YKPIV_KEY_RETIRED1
        || key > YKPIV_KEY_RETIRED20 && (key < YKPIV_KEY_AUTHENTICATION)
        || key > YKPIV_KEY_CARDAUTH && (key != YKPIV_KEY_ATTESTATION)
    {
        return ErrorKind::KeyError;
    }
    if pin_policy != YKPIV_PINPOLICY_DEFAULT
        && (pin_policy != YKPIV_PINPOLICY_NEVER)
        && (pin_policy != YKPIV_PINPOLICY_ONCE)
        && (pin_policy != YKPIV_PINPOLICY_ALWAYS)
    {
        return ErrorKind::GenericError;
    }
    if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT
        && (touch_policy != YKPIV_TOUCHPOLICY_NEVER)
        && (touch_policy != YKPIV_TOUCHPOLICY_ALWAYS)
        && (touch_policy != YKPIV_TOUCHPOLICY_CACHED)
    {
        return ErrorKind::GenericError;
    }
    match algorithm {
        YKPIV_ALGO_RSA1024 | YKPIV_ALGO_RSA2048 => {
            if p_len + q_len + dp_len + dq_len + qinv_len >= 1024 {
                return ErrorKind::SizeError;
            } else {
                if algorithm == YKPIV_ALGO_RSA1024 {
                    elem_len = 64;
                }
                if algorithm == YKPIV_ALGO_RSA2048 {
                    elem_len = 128;
                }
                if p.is_null() || q.is_null() || dp.is_null() || dq.is_null() || qinv.is_null() {
                    return ErrorKind::GenericError;
                }
                params[0] = p;
                lens[0] = p_len;
                params[1] = q;
                lens[1] = q_len;
                params[2] = dp;
                lens[2] = dp_len;
                params[3] = dq;
                lens[3] = dq_len;
                params[4] = qinv;
                lens[4] = qinv_len;
                param_tag = 0x1;
                n_params = 5u8;
            }
        }
        YKPIV_ALGO_ECCP256 | YKPIV_ALGO_ECCP384 => {
            if ec_data_len as (usize) >= key_data.len() {
                return ErrorKind::SizeError;
            }
            if algorithm == YKPIV_ALGO_ECCP256 {
                elem_len = 32;
            } else if algorithm == YKPIV_ALGO_ECCP384 {
                elem_len = 48;
            }
            if ec_data.is_null() {
                return ErrorKind::GenericError;
            }
            params[0] = ec_data;
            lens[0] = ec_data_len as usize;
            param_tag = 0x6;
            n_params = 1;
        }
        _ => return ErrorKind::AlgorithmError,
    }
    for i in 0..n_params {
        *in_ptr = (param_tag + i as i32) as u8;
        in_ptr = in_ptr.offset(1);
        in_ptr = in_ptr.add(_ykpiv_set_length(in_ptr, elem_len as usize));
        let padding = (elem_len as (usize)).wrapping_sub(lens[i as usize]);
        let remaining = (key_data.as_mut_ptr() as usize) + 1024 - in_ptr as usize;
        if padding > remaining {
            return ErrorKind::AlgorithmError;
        }
        memset(in_ptr as *mut c_void, 0, padding);
        in_ptr = in_ptr.add(padding);
        memcpy(
            in_ptr as *mut c_void,
            params[i as usize] as *const c_void,
            lens[i as usize],
        );
        in_ptr = in_ptr.add(lens[i as usize]);
    }
    if pin_policy != YKPIV_PINPOLICY_DEFAULT {
        *in_ptr = YKPIV_PINPOLICY_TAG;
        *in_ptr.add(1) = 0x01;
        *in_ptr.add(2) = pin_policy;
        in_ptr = in_ptr.add(3);
    }
    if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT {
        *in_ptr = YKPIV_TOUCHPOLICY_TAG;
        *in_ptr.add(1) = 0x01;
        *in_ptr.add(2) = touch_policy;
        in_ptr = in_ptr.add(3);
    }
    if _ykpiv_begin_transaction(state) != ErrorKind::Ok {
        return ErrorKind::PcscError;
    } else if _ykpiv_ensure_application_selected(state) == ErrorKind::Ok {
        res = ykpiv_transfer_data(
            state,
            templ.as_ptr(),
            key_data.as_mut_ptr(),
            in_ptr as isize - key_data.as_mut_ptr() as isize,
            data.as_mut_ptr(),
            &mut recv_len,
            &mut sw,
        );
        if res == ErrorKind::Ok && sw != SW_SUCCESS {
            res = ErrorKind::GenericError;
            if sw == SW_ERR_SECURITY_STATUS {
                res = ErrorKind::AuthenticationError;
            }
        }
    }
    key_data.zeroize();
    _ykpiv_end_transaction(state);
    res
}
pub unsafe fn ykpiv_import_private_key ( state : * mut YubiKey , key : u8 , algorithm : u8 , p : * const u8 , p_len : usize , q : * const u8 , q_len : usize , dp : * const u8 , dp_len : usize , dq : * const u8 , dq_len : usize , qinv : * const u8 , qinv_len : usize , ec_data : * const u8 , ec_data_len : u8 , pin_policy : u8 , touch_policy : u8 , ) -> ErrorKind { let mut key_data = [ 0u8 ; 1024 ] ; let mut in_ptr : * mut u8 = key_data . as_mut_ptr ( ) ; let templ = [ 0 , YKPIV_INS_IMPORT_KEY , algorithm , key ] ; let mut data = [ 0u8 ; 256 ] ; let mut recv_len = data . len ( ) ; let mut elem_len : u32 = 0 ; let mut sw : i32 = 0 ; let mut params : [ * const u8 ; 5 ] = [ ptr :: null ( ) ; 5 ] ; let mut lens = [ 0usize ; 5 ] ; let n_params : u8 ; let param_tag : i32 ; let mut res = ErrorKind :: Ok ; if state . is_null ( ) { return ErrorKind :: GenericError ; } if key == YKPIV_KEY_CARDMGM || key < YKPIV_KEY_RETIRED1 || key > YKPIV_KEY_RETIRED20 && ( key < YKPIV_KEY_AUTHENTICATION ) || key > YKPIV_KEY_CARDAUTH && ( key != YKPIV_KEY_ATTESTATION ) { return ErrorKind :: KeyError ; } if pin_policy != YKPIV_PINPOLICY_DEFAULT && ( pin_policy != YKPIV_PINPOLICY_NEVER ) && ( pin_policy != YKPIV_PINPOLICY_ONCE ) && ( pin_policy != YKPIV_PINPOLICY_ALWAYS ) { return ErrorKind :: GenericError ; } if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT && ( touch_policy != YKPIV_TOUCHPOLICY_NEVER ) && ( touch_policy != YKPIV_TOUCHPOLICY_ALWAYS ) && ( touch_policy != YKPIV_TOUCHPOLICY_CACHED ) { return ErrorKind :: GenericError ; } match algorithm { YKPIV_ALGO_RSA1024 | YKPIV_ALGO_RSA2048 => { if p_len + q_len + dp_len + dq_len + qinv_len >= 1024 { return ErrorKind :: SizeError ; } else { if algorithm == YKPIV_ALGO_RSA1024 { elem_len = 64 ; } if algorithm == YKPIV_ALGO_RSA2048 { elem_len = 128 ; } if p . is_null ( ) || q . is_null ( ) || dp . is_null ( ) || dq . is_null ( ) || qinv . is_null ( ) { return ErrorKind :: GenericError ; } params [ 0 ] = p ; lens [ 0 ] = p_len ; params [ 1 ] = q ; lens [ 1 ] = q_len ; params [ 2 ] = dp ; lens [ 2 ] = dp_len ; params [ 3 ] = dq ; lens [ 3 ] = dq_len ; params [ 4 ] = qinv ; lens [ 4 ] = qinv_len ; param_tag = 0x1 ; n_params = 5u8 ; } } YKPIV_ALGO_ECCP256 | YKPIV_ALGO_ECCP384 => { if ec_data_len as ( usize ) >= key_data . len ( ) { return ErrorKind :: SizeError ; } if algorithm == YKPIV_ALGO_ECCP256 { elem_len = 32 ; } else if algorithm == YKPIV_ALGO_ECCP384 { elem_len = 48 ; } if ec_data . is_null ( ) { return ErrorKind :: GenericError ; } params [ 0 ] = ec_data ; lens [ 0 ] = ec_data_len as usize ; param_tag = 0x6 ; n_params = 1 ; } _ => return ErrorKind :: AlgorithmError , } for i in 0 .. n_params { * in_ptr = ( param_tag + i as i32 ) as u8 ; in_ptr = in_ptr . offset ( 1 ) ; in_ptr = in_ptr . add ( _ykpiv_set_length ( in_ptr , elem_len as usize ) ) ; let padding = ( elem_len as ( usize ) ) . wrapping_sub ( lens [ i as usize ] ) ; let remaining = ( key_data . as_mut_ptr ( ) as usize ) + 1024 - in_ptr as usize ; if padding > remaining { return ErrorKind :: AlgorithmError ; } memset ( in_ptr as * mut c_void , 0 , padding ) ; in_ptr = in_ptr . add ( padding ) ; memcpy ( in_ptr as * mut c_void , params [ i as usize ] as * const c_void , lens [ i as usize ] , ) ; in_ptr = in_ptr . add ( lens [ i as usize ] ) ; } if pin_policy != YKPIV_PINPOLICY_DEFAULT { * in_ptr = YKPIV_PINPOLICY_TAG ; * in_ptr . add ( 1 ) = 0x01 ; * in_ptr . add ( 2 ) = pin_policy ; in_ptr = in_ptr . add ( 3 ) ; } if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT { * in_ptr = YKPIV_TOUCHPOLICY_TAG ; * in_ptr . add ( 1 ) = 0x01 ; * in_ptr . add ( 2 ) = touch_policy ; in_ptr = in_ptr . add ( 3 ) ; } if _ykpiv_begin_transaction ( state ) != ErrorKind :: Ok { return ErrorKind :: PcscError ; } else if _ykpiv_ensure_application_selected ( state ) == ErrorKind :: Ok { res = ykpiv_transfer_data ( state , templ . as_ptr ( ) , key_data . as_mut_ptr ( ) , in_ptr as isize - key_data . as_mut_ptr ( ) as isize , data . as_mut_ptr ( ) , & mut recv_len , & mut sw , ) ; if res == ErrorKind :: Ok && sw != SW_SUCCESS { res = ErrorKind :: GenericError ; if sw == SW_ERR_SECURITY_STATUS { res = ErrorKind :: AuthenticationError ; } } } key_data . zeroize ( ) ; _ykpiv_end_transaction ( state ) ; res }
Import a private encryption or signing key into the YubiKey
Import a private encryption or signing key into the YubiKey
state
*mut YubiKey
key
u8
algorithm
u8
p
*const u8
p_len
usize
q
*const u8
q_len
usize
dp
*const u8
dp_len
usize
dq
*const u8
dq_len
usize
qinv
*const u8
qinv_len
usize
ec_data
*const u8
ec_data_len
u8
pin_policy
u8
touch_policy
u8