fn create_inner()

in key/aziot-keys/src/key_pair.rs [629:736]


fn create_inner(
    locations: &[crate::implementation::Location],
    preferred_algorithms: &[PreferredAlgorithm],
) -> Result<(), crate::AZIOT_KEYS_RC> {
    let location = locations
        .first()
        .ok_or_else(|| crate::implementation::err_external("no valid location for key pair"))?;
    match location {
        crate::implementation::Location::Filesystem(path) => {
            let preferred_algorithm =
                preferred_algorithms.iter().copied().next().ok_or_else(|| {
                    crate::implementation::err_invalid_parameter(
                        "preferred_algorithms",
                        "none specified",
                    )
                })?;

            let private_key = match preferred_algorithm {
                PreferredAlgorithm::NistP256 => {
                    let mut group =
                        openssl::ec::EcGroup::from_curve_name(openssl::nid::Nid::X9_62_PRIME256V1)?;
                    group.set_asn1_flag(openssl::ec::Asn1Flag::NAMED_CURVE);
                    let ec_key = openssl::ec::EcKey::generate(&group)?;
                    let private_key = openssl::pkey::PKey::from_ec_key(ec_key)?;
                    private_key
                }

                PreferredAlgorithm::Rsa2048 => {
                    let rsa = openssl::rsa::Rsa::generate(2048)?;
                    let private_key = openssl::pkey::PKey::from_rsa(rsa)?;
                    private_key
                }

                PreferredAlgorithm::Rsa4096 => {
                    let rsa = openssl::rsa::Rsa::generate(4096)?;
                    let private_key = openssl::pkey::PKey::from_rsa(rsa)?;
                    private_key
                }
            };

            let private_key_pem = private_key.private_key_to_pem_pkcs8()?;
            std::fs::write(path, private_key_pem).map_err(crate::implementation::err_external)?;

            Ok(())
        }

        crate::implementation::Location::Pkcs11 { lib_path, uri } => {
            let pkcs11_context = pkcs11::Context::load(lib_path.clone())
                .map_err(crate::implementation::err_external)?;
            let pkcs11_slot = pkcs11_context
                .find_slot(&uri.slot_identifier)
                .map_err(crate::implementation::err_external)?;
            let pkcs11_session = pkcs11_context
                .open_session(pkcs11_slot, uri.pin.clone())
                .map_err(crate::implementation::err_external)?;

            for preferred_algorithm in preferred_algorithms {
                match preferred_algorithm {
                    PreferredAlgorithm::NistP256 => {
                        if pkcs11_session
                            .clone()
                            .generate_ec_key_pair(
                                openssl2::EcCurve::NistP256,
                                uri.object_label.as_deref(),
                            )
                            .is_ok()
                        {
                            return Ok(());
                        }
                    }

                    PreferredAlgorithm::Rsa2048 => {
                        let exponent = openssl_sys::RSA_F4;
                        let exponent = exponent.to_be_bytes();
                        let exponent = openssl::bn::BigNum::from_slice(&exponent)?;

                        if pkcs11_session
                            .clone()
                            .generate_rsa_key_pair(2048, &exponent, uri.object_label.as_deref())
                            .is_ok()
                        {
                            return Ok(());
                        }
                    }

                    PreferredAlgorithm::Rsa4096 => {
                        let exponent = openssl_sys::RSA_F4;
                        let exponent = exponent.to_be_bytes();
                        let exponent = openssl::bn::BigNum::from_slice(&exponent)?;

                        if pkcs11_session
                            .clone()
                            .generate_rsa_key_pair(4096, &exponent, uri.object_label.as_deref())
                            .is_ok()
                        {
                            return Ok(());
                        }
                    }
                }
            }

            Err(crate::implementation::err_invalid_parameter(
                "preferred_algorithms",
                "no algorithm succeeded",
            ))
        }
    }
}