fn configure_oaep_crypto_operation()

in aws-lc-rs/src/rsa/encryption/oaep.rs [274:324]


fn configure_oaep_crypto_operation(
    evp_pkey_ctx: &mut LcPtr<EVP_PKEY_CTX>,
    oaep_hash_fn: OaepHashFn,
    mgf1_hash_fn: Mgf1HashFn,
    label: Option<&[u8]>,
) -> Result<(), Unspecified> {
    if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(*evp_pkey_ctx.as_mut(), RSA_PKCS1_OAEP_PADDING) }
    {
        return Err(Unspecified);
    }

    if 1 != unsafe { EVP_PKEY_CTX_set_rsa_oaep_md(*evp_pkey_ctx.as_mut(), oaep_hash_fn()) } {
        return Err(Unspecified);
    }

    if 1 != unsafe { EVP_PKEY_CTX_set_rsa_mgf1_md(*evp_pkey_ctx.as_mut(), mgf1_hash_fn()) } {
        return Err(Unspecified);
    }

    let label = label.unwrap_or(&[0u8; 0]);

    if label.is_empty() {
        // Safety: Don't pass zero-length slice pointers to C code :)
        if 1 != unsafe { EVP_PKEY_CTX_set0_rsa_oaep_label(*evp_pkey_ctx.as_mut(), null_mut(), 0) } {
            return Err(Unspecified);
        }
        return Ok(());
    }

    // AWS-LC takes ownership of the label memory, and will call OPENSSL_free, so we are forced to copy it for now.
    let mut label_ptr =
        DetachableLcPtr::<u8>::new(unsafe { OPENSSL_malloc(size_of_val(label)) }.cast())?;

    {
        // memcpy the label data into the AWS-LC allocation
        let label_ptr =
            unsafe { core::slice::from_raw_parts_mut(*label_ptr.as_mut(), label.len()) };
        label_ptr.copy_from_slice(label);
    }

    if 1 != unsafe {
        EVP_PKEY_CTX_set0_rsa_oaep_label(*evp_pkey_ctx.as_mut(), *label_ptr, label.len())
    } {
        return Err(Unspecified);
    }

    // AWS-LC owns the allocation now, so we detach it to avoid freeing it here when label_ptr goes out of scope.
    label_ptr.detach();

    Ok(())
}