All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.
Re-enabling AES-NI on VPSes that don't pass the feature through
Have you ever had a VPS that isn't using CPU passthrough and is not exposing AES-NI, causing really, really slow encryption? Or have you ever asked your provider to enable it but instead gotten kicked out for being "too advanced"? The solution is quite simple and just involves setting OPENSSL_ia32cap. Just run, as root:
openssl info -cpusettings | perl -pe 's/(0x[0-9a-f]{16})/sprintf("0x%016x", hex($1) | (1 << 57))/e' >> /etc/environment
Don't just copy-paste this. There's an invisible character in -pe to prevent Cloudflare from thinking this is an exploit. 🙄
So how does this work, exactly? The hypervisor, if it's not set to CPU passthrough or is not set to expose a CPU model that supports AES-NI, simply modifies the results of the CPUID instruction (it's trapped and then emulated) to not advertise the feature but, crucially, doesn't actually prevent the AES-NI instructions from working. Whenever the guest attempts to determine CPU features using CPUID, it will be told that AES-NI is not supported (even if it is!) and it will fall back to a slower, all-software implementation. But the OpenSSL library has the ability to override that detection using an environmental variable. All this one-liner does is get the exposed CPUID value, OR the value of 1 << 57 with the first logical vector, and append it to the environment file. Beware that this change is persistent and tied to the hardware you first run it on so things may break if the VPS is migrated.
Of course, the host's hardware has to actually support AES-NI. Anything in the last decade and a half is sure to, but don't expect an ancient Core2Duo to magically become an encryption beast by running this (or do anything other than crash, because this trick does disable OpenSSL's normal feature auto-detection). Also, note this only improves the performance of OpenSSL-based cryptography. Kernel cryptography will not be changed. To change that, you'd have to write a kernel module (sorry, your encrypted swap isn't getting any faster otherwise).
This trick can also be used to enable other features that might be missing, such as AVX2, RDRAND, etc. See the linked OpenSSL documentation to determine what bit to enable. Small adjustments to the Perl one-liner (beyond simply changing the bit shift amount) will be necessary if the bit is not in LV0.
There are some posts on this forum claiming that you only need to set OPENSSL_ia32cap=+0x200000200000000, but that is wrong as it will disable all other CPU features. Unfortunately, you really have to parse the entire damn string and fix it up, but Perl is really good for this kind of trick because it is designed for text processing.
If you have kernel 6.15 or newer, add this to your kernel command line and you'll also gain AES-NI acceleration in the kernel (for example, encrypted block devices or anything else that relies on the crypto API):
setcpuid=153
You can do that by adding it to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub and then running update-grub and rebooting. This will bring "aes" back to /etc/cpuinfo, but I don't believe that will change OpenSSL's behavior on its own. For that, you still need the environmental variable trick.


Comments
I just let myself got kicked out for being too advanced instead of running the command. Worth it.
If i explicitly remove the CPU flag in qemu how can this reenable it? Is it emulated?
Because all QEMU does is change the effect of the CPUID instruction to stop advertising AES-NI support. But the AES-NI instructions can't be trapped, so they'll always work if the guest attempts to issue them and the hardware supports them.
(Edited the OP to add a more detailed explanation)
Oh okay that's actually nice. Good finding.
tempted to run this on a GCORE vps which shows QEMU virtual cpu with nothing enabled
You can test it out just by removing the
>> /etc/environmentpart. It'll output something like this:Just export that as an ennvironmental variable and try
openssl speedand see if it gets faster.Note that sometimes it'll show a QEMU virtual CPU but still support AES-NI, for example if it started with
-cpu qemu64,aes. You can check ifaesis present in/proc/cpuinfoto see if AES-NI export is advertised. If not, this trick may help!It's a bit pointless, unless you know why you need it. Modern SSH, HTTPS and VPN (Wireguard) have moved on from AES to ChaCha20, and that doesn't rely on any hardware acceleration.
AES with AES-NI is still significantly faster than software-only ChaCha20. It's quite useful for applications where you need AES, such as Tor relays or web servers that can't just tell older TLS 1.2 users to screw off.
It's not
A bit faster at the largest block size, but slower on all others, up to 10x. Checked on my home server with AMD Ryzen 5900X, bare metal (no VPS).
Sure, with Tor there is no choice what to use.
That's because you were using AES in GCM mode which requires an extra encryption step to compute the authentication tag for each block (which is really bad with small block sizes). Try it in CTR mode. It will be faster.
Another test on a different (and more idle) system:
(Fastest is bold)
Here, 256-bit AES ranges from twice as fast to four times as fast as software ChaCha.
Yeah, it appears Tor actually uses CTR, and they are replacing it with something else.
That's just the circuit layer encryption. It also has to do link-level encryption as well, which is TLS and is usually AES-GCM or ChaCha20-Poly1305, so that's a double whammy! Thankfully, TLS has a 16 KiB record size, so it doesn't use the small blocks that make GCM bad, and CGO still has the performance characteristics of CTR.
But raw AES with AES-NI will always be faster than software-only ChaCha20, as long as it's not put in a mode that's inefficient with small block sizes. No matter what it is, it's better than CCM!
All that said, I actually prefer ChaCha20 in nearly all situations even if it's slightly slower. It has a higher security margin and it's much easier to implement in software without causing a zillion side-channel vulnerabilities. The only downside is that its construction (ARX, aka Add-Rotate-XOR) is somewhat less well-understood as far as cryptanalysis goes than AES (a much more traditional substitution-permutation network), but that's rapidly changing.
Thankfully we have Cryptography Stack Exchange moderator at home
Annoyingly, people keep using LLMs to try to post answers, and LLMs seem to be really bad with anything cryptography related. It's against the rules for them to do so, but these days it can be hard to tell if an answer is just shitty or is AI...
We actually went on strike a while ago to protest the then-current rules that determined when we were allowed to delete and ban for LLM violations, and Stack Exchange staff were hilariously adamant not to refer to it as a "strike" because they don't want us to be legally considered employees, because then we'd have rights.
Okay this is pretty cool, I didn't know this flag existed.
Just that I had to use
153(X86_FEATURE_AES) instead of57on my Linux 7.0 VM.According to dmesg
57enablesfxsr_optfor me:(Unless
fxsr_optis what enables AES acceleration in kernel?)Oops, 153 is correct! It's definitely not related to FXSAVE/FXRSTOR optimizations! Somehow I was assuming it would be the bit offset in CPUID rather than some Linux-specific constant? But now I can't edit my post, it's too late...
@angstrom Is there any chance you could replace
setcpuid=57withsetcpuid=153in the OP (at the very bottom)?Thanks for this information! While I don't need it, great to know. I'm curious tho, if this allows breaking the sandbox of QEMU to some extent..? Seems to be the case, as long as some hardware implementation is present in the CPU (curious about PCIe and other stuff in this regard)
Also thanks for the discussion regarding ChaCha20 & GCM/CTR
This is the LET I need
It doesn't break the sandbox at all. Security-related instructions are indeed protected, but something like AES-NI or any other basic ISA extension is not something that the hypervisor can actually block. For performance, only a small subset of critical instructions and instruction behavior can be trapped by the hypervisor. This is because they didn't want to implement what amounts to a costly
if (is_in_vm && trap_is_enabled) trigger_vmexit;check on every single instruction.Fun fact: Host CPU passthrough in QEMU (
-cpu host) is basically nothing more than setting thattrap_is_enabledto false for the CPUID instruction, so the guest gets to see the full info! But-cpu qemu64sets it to trap, which forcibly kicks execution out of the guest and back to the hypervisor upon trying to execute CPUID, and the hypervisor then emulates it before returning back to the guest with custom contents in the registers, basically lying to the guest about CPU features.Important instructions like CPUID, HLT, IN, and OUT can trap, and instructions doing important things like a MOV trying to access privileged memory can trap, but fast-path instructions like XOR, TEST, and AESENC can't trap.
PCIe stuff is done using MMIO (memory-mapped I/O), and the hypervisor is able to trap on memory access, so it can prevent the guest from accessing actual hardware unless that hardware is passed through (e.g. with VFIO).
Yes. I really appreciate when people with expertise do these voluntary works, or preventing well-poisoning. LLM doesn't have that capability yet.
LOL. The management must have suck at their job. There's not much of difference of spamming with or without LLM
Oh. My. God. They do. No one has any faith in the company anymore. Not even the moderators. The company, ever since being bought out by a VC firm, is trying desperately to try to increase profit by hampering mod's ability to do our job (more low-quality questions and spammers == more engagement and revenue!!1), adding AI-this and AI-that everywhere, coming up with nonsense initiatives that do literally nothing, removing the dates from comments so people are more likely to reply to 15 year old comments thinking they're recent (more engagement == more revenue!!!111one), adding small ads between comments to trick people into thinking the ads are actual comments, firing moderators for questioning a yet-unreleased code of conduct change, doxxing and defaming the moderator in the press and then getting successfully sued by said moderator, illegally and retroactively changing licenses, and much more. It's honestly like watching a slow motion train wreck.
Oh yeah, and they embed hidden, covert hardware fingerprinter trackers in ads that bypass cookie settings by tracking unique hardware characteristics so you can't evade it by deleting cookies. And then they lie about it and get called out.
Replaced as requested
@forest
Great work, great "how-to", thank you!
That said I don't care because I'd rather leave/cancel with a provider willfully or stupidly trying to cripple their products wrt. security.
So, no @DediRock VPS for me *g
Same, but it looks like it's expecting "CPU feature bit" like those defined in from asm/cpufeatures.h
Also seems like you can enable multiple features just by separating the values with a comma.
For example
setcpuid=129,137,153,147,148:But a bit sad this won't affect apps detecting flags using the
cpuidinstruction.Yeah, it'll only affect the kernel's decisions and applications that use the AF_ALG Crypto API. Anything else would require custom changes to the applications themselves. It's just lucky that OpenSSL uses an environmental variable to override CPUID checks, but I'm sure many other applications don't, so you'd have to use an
LD_PRELOADhook or something to hijack its detection routines.Thanks, tried it on Gcore and there is a very marginal increase of speed, not sure whether it will have an effect but I guess it does not harm.
Did you reboot after editing the environment, and
echo $OPENSSL_ia32capshows something?Not initially but rebooted now.
shows
0x82202001478bfffd:0x0000000000000000:0x0000000000000000:0x0000000000000000:0x0000000000000000Huh, the others shouldn't be zeroed out unless there was something wrong with my Perl (or the CPU is very old), but I tested it and it should be super simple.
What does
openssl info -cpusettingssay?Returns
OPENSSL_ia32cap=0x82202001478bfffd:0x0000000000000000:0x0000000000000000:0x0000000000000000:0x0000000000000000 env:0x82202001478bfffd:0x0000000000000000:0x0000000000000000:0x0000000000000000:0x0000000000000000And if you do
unset OPENSSL_ia32cap; openssl info -cpusettings?