The NIST has "defined" 15 "standard curves", specified in FIPS 186-4. Actually, they did not define them themselves; they inherited them from SEC. These 15 curves aggregate into 3 groups:
- The P-* curves work in a "prime field" (point coordinates are integers modulo a prime p).
- The B-* curves work in a "binary field" (point coordinates are values in GF(2m)).
- The K-* curves work in the same fields as the B-* curves, but have a special structure which allows for faster computations.
NIST found out that there was a huge reluctance to implement support for these 15 curves, let alone for "general" curves, for a variety of reasons:
- The involved mathematics are felt to be "hard" (that's harder to grasp than RSA or plain Diffie-Hellman).
- ... even more so for curves in binary fields.
- While it is possible to write "generic" curve-handling code, code which targets a specific curve is often simpler to implement and faster. In particular, the P-* curves work modulo prime values whose format makes implementation more efficient (fast modular reduction).
- There have been recurrent and long-standing claims of patents, making the use of elliptic curve "risky".
- ... especially for curves in binary fields;
- ... and more generally for generic curves chosen to have some characteristic which is beneficial to implementation. It is not known whether a curve can be patented (as opposed to an implementation technique supported by a special curve structure), but uncertainty already does powerful dissuasion.
Thus, people were wary of implementing generic support for elliptic curves, because it seemed to be hard, detrimental to performance, and a legal minefield. Sticking to a few of the simpler curves seemed easier, faster and safer; and that's what happened. NIST (well, NSA) formalized this trend as their "suite B" cryptography suite, which mandates implementation of exactly two curves: P-256 and P-384.
In SSL/TLS and in X.509, arbitrary curves may be used. However, most implementations won't support arbitrary curves. OpenSSL supports all 15 NIST curves, but not arbitrary curves. Firefox supports only P-256 and P-384; I am not sure Microsoft's code (Windows, hence Internet Explorer) will accept more than that either (maybe P-521 as well). If you try to use any other curve than P-256 or P-384, then you will encounter interoperability issues (more issues than what you already get by trying to use elliptic curves at all). Some standard writers, feeling that they must "be practical", have fully admitted this fact, and just banned the use of other curves, as you see in RFC 5480.
Generating your own curve is not hard, but substantially harder than generating your own DH parameters. It involves point counting with Schoof's algorithm or a variant thereof. You won't be able to slap together a curve generator in one hour and a hundred lines of Java code, whereas producing DH parameters can be done under these constraints. The computational cost is also higher (you will still get a nice curve in a minute, but not in 100ms). To be brief, people don't do that often, or at all.