zkVMs (of which RISC Zero is one example)
do not require a TEE. That's the whole point: the privacy properties come out of the math. Basically, nowadays, once you and I can agree on the text of a program, you can run the program on your private inputs and produce a number that
proves to me that you actually ran this specific program and not some other.
For example, age verification: I can run a program that takes a signed time-stamp and an officially-signed birth certificate and produces a yes/no "over 18" boolean, then prove to you I actually ran this program, not just "return true", but WITHOUT revealing the birth certificate.
It's a really neat facility that too few people are thinking about. We've had zero knowledge systems for a few decades now, but until now, each one has been a special bespoke mathematical object that would take years to develop. Over the past year or two, we've 1) made the things 1000x faster, and 2) made it possible to write arbitrary code under zero knowledge instead of having to make each ZK system a PHD thesis.
Others say that zkVMs are pointless because they're less efficient than these bespoke mathematical objects. Yes, they are. So what? The flexibility is worth it. Others say that zkVMs came out of Etherium, so they're only good for "crypto" stuff. False. Sure, it's the Etherium people who did a lot of foundational research into efficient zkVMs. We owe them a debt of gratitude, because they made a new kind of CS object that's going to be useful for tons of things not tied to Etherium or web3 in any way.
Anyway, if you want to get a feel for fully programmable ZK systems, check out https://noir-lang.org/, a programming language for ZK programs (not a zkVM, but same UX). Or https://github.com/a16z/jolt, which lets you run normal Rust under zero knowledge.
Today, you can write normal-looking code and have it execute under zero knowledge, and, importantly, efficiently. You literally couldn't do this two years ago, and it changes everything.