bssl-crypto: Fix Ed25519 SPKI parser to check key types

Otherwise it mistakenly interprets an X25519 SPKI as an Ed25519 key.
Once that is fixed, a number of these error conditions are impossible.

Change-Id: Iffd116252f1f632f8f917c56b1676069686eddbf
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81587
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/rust/bssl-crypto/src/ed25519.rs b/rust/bssl-crypto/src/ed25519.rs
index 73c90fb..6be0508 100644
--- a/rust/bssl-crypto/src/ed25519.rs
+++ b/rust/bssl-crypto/src/ed25519.rs
@@ -161,32 +161,23 @@
             // Safety: cbs is valid per `parse_with_cbs`.
             |cbs| unsafe { bssl_sys::EVP_parse_public_key(cbs) },
         )?);
-
-        let mut out_len = 0;
-        // When the out buffer is null, `out_len` is set to the size of the raw public key.
-        // Safety: the arguments are valid.
-        let result = unsafe {
-            bssl_sys::EVP_PKEY_get_raw_public_key(
-                pkey.as_ffi_ptr(),
-                core::ptr::null_mut(),
-                &mut out_len,
-            )
-        };
-        if result != 1 {
-            return None;
-        }
-        if out_len != PUBLIC_KEY_LEN {
+        // Safety: `pkey` is a valid `EVP_PKEY`.
+        if unsafe { bssl_sys::EVP_PKEY_id(pkey.as_ffi_ptr()) } != bssl_sys::EVP_PKEY_ED25519 {
             return None;
         }
 
-        // When the out buffer is not null, the raw public key is written into it.
-        // Safety: the arguments are valid.
+        // Safety: `EVP_PKEY_get_raw_public_key` is passed a valid buffer. The
+        // (always true) assertion ensures the closure always initializes the
+        // array.
         let raw_pkey: [u8; PUBLIC_KEY_LEN] = unsafe {
-            with_output_array(|out, _| {
+            with_output_array(|out, mut out_len| {
+                // If `pkey` is an Ed25519 key, checked above, the raw public
+                // key must be available, and must be `PUBLIC_KEY_LEN` bytes.
                 assert_eq!(
                     1,
                     bssl_sys::EVP_PKEY_get_raw_public_key(pkey.as_ffi_ptr(), out, &mut out_len)
                 );
+                assert_eq!(out_len, PUBLIC_KEY_LEN);
             })
         };
         Some(PublicKey(raw_pkey))
@@ -269,6 +260,14 @@
     }
 
     #[test]
+    fn der_subject_public_key_info_wrong_type() {
+        // This is an X25519 key, not an Ed25519 key.
+        let spki = test_helpers::decode_hex_into_vec("302a300506032b656e032100e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c");
+        // `from_der_subject_public_key_info` should reject it.
+        assert!(PublicKey::from_der_subject_public_key_info(&spki).is_none());
+    }
+
+    #[test]
     fn empty_msg() {
         // Test Case 1 from RFC test vectors: https://www.rfc-editor.org/rfc/rfc8032#section-7.1
         let pk = test_helpers::decode_hex(