Of course it sends the keys to WhatsApp! If you install the client on a second phone, it just works, right?
So they're either:
1) generating a new key on each device and encrypting all incoming messages to every client's public key (or just encrypting the session key, a la PGP. -- While this isn't sending the key back to the mothership, new keys can be added at will, so copying traffic is easy.)
2) generating one key per account and shuffling it to newly installed clients through their server (possibly encrypted with the user's password... which they already know)
3) generating a key from the user's password directly with PBKDF2 or the like (a la SpiderOak, but (like SpiderOak) the client is closed source and they already know your password or could get it easily).
4) randomly assigning a symmetric key to each session and communicating it in-band to the clients involved in the chat.
Personally, I think 3 or 4 are the most likely because the infrastructure is the easiest and it still carries "end-to-end encryption" buzzword compliance.
The single hardest part of properly using encryption is key management. It's also the most vulnerable aspect of even weak crypto. Anything that simplifies this for end users, without requiring anything of them, is likely making serious security/convenience compromises.
[I'm still a big fan of hardware tokens for key storage and decryption. It greatly simplifies user key management while giving the user something familiar to associate their "key" with. It's not perfectly secure, but having to compromise a smartcard secure element requires more of the adversary.]