There is no real standard for things in "PEM" format. There was a proposed standard called Privacy-enhanced Electronic Mail, from which the "PEM" acronym was derived; however, that standard never gained traction against its competition (PGP and S/MIME) and nobody implements it.
OpenSSL picked up PEM and "enhanced" the PEM format with extra functionalities and headers, without any actual specification or documentation worth that name, so that nowadays, "PEM" really means "whatever OpenSSL produces and can parse". Other vendors followed, e.g. Microsoft, whose software can decode PEM-encoded certificates.
The principle of PEM (Base64-encoded data, with a '-----BEGIN XXX-----' header and corresponding '-----END XXX-----' trailer) has been used for other things; PGP calls it "ASCII armor". The point of that way of doing things is to be able to locate the interesting data within a sequence of text data, regardless of the various tortures inflicted to that text as it is transferred (e.g. sent as e-mail, copy&pasted, included in a Word document, printed and scanned...). This is an important point: it means that the whole point of PEM is to be able to store the certificates together and haphazardly without having to follow a specific, precise standard. In that sense, a standard for a "PEM bundle" would be a self-contradiction: a "PEM bundle" is what you do when there is no standard.
It is not incorrect to call it a "de facto standard".
When you want to encode and send certificates, there are in fact more than two methods; possibilities include:
- Encode each certificate separately, using ASN.1 DER encoding (which is standard).
- Use PEM to further make these certificates more resilient to ASCII-based transfer; this also allows storing several of them in a single file (that which you call a "PEM bundle");
- Store the certificates in a PKCS#7 (aka CMS)
SignedData
object. A SignedData
is nominally a format for embedding data which is signed; but you can omit the data and include exactly zero signature, in which case you have some sort of shell that includes a field for embedding "extra certificates" (nominally, these certificates are there to help in validating the signatures). This is the reuse of an existing standard for something that the standard was not meant to do, but existing software does that. Microsoft calls that a "PKCS#7 certificate" or a "P7B file".
- Use a PKCS#7
SignedData
but also PEM-encode it (so you could conceptually store several of them in a single file).
- PKCS#12 (also known as "PFX"). This format also allows storing other kind of objects, and includes provisions for password-based encryption, so it is commonly used to store a certificate and its private key. (Apparently, nobody ever thought of PEM-encoding a PKCS#12 archive.)
Private keys also have their own formats. For instance, PKCS#1 defines an ASN.1-based encoding for RSA private keys, that OpenSSL will gleefully use and then PEM-encode with a "BEGIN RSA PRIVATE KEY" header. That format may be further wrapped into a PKCS#8 object, which includes an ASN.1-based identifier for the algorithm, and also optional support of password-based encryption; and then, OpenSSL will also encode a PKCS#8 file, this time with "BEGIN PRIVATE KEY" or "BEGIN ENCRYPTED PRIVATE KEY" (no indication of the algorithm in the PEM header), depending on whether password-based encryption was used or not. Alternatively, the raw PKCS#1 format may also be password-encrypted, using the extensions to PEM that OpenSSL implements but does not document (OpenSSL's source code being supposed to be the specification).
To sum up: it is a mess.