Alice Wang | 000595b | 2023-10-02 13:46:45 +0000 | [diff] [blame] | 1 | // Copyright 2023, The Android Open Source Project |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
Alice Wang | 7468ae4 | 2023-11-30 10:20:36 +0000 | [diff] [blame] | 15 | use bssl_avf::{sha256, ApiName, Digester, EcKey, EcdsaError, Error, PKey, Result}; |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 16 | use coset::CborSerializable; |
Alice Wang | 600ea5b | 2023-11-17 15:12:16 +0000 | [diff] [blame] | 17 | use spki::{ |
Andrew Walbran | 5b879eb | 2023-12-18 13:49:02 +0000 | [diff] [blame^] | 18 | der::{AnyRef, Decode, Encode}, |
| 19 | AlgorithmIdentifier, ObjectIdentifier, SubjectPublicKeyInfoRef, |
Alice Wang | 600ea5b | 2023-11-17 15:12:16 +0000 | [diff] [blame] | 20 | }; |
| 21 | |
| 22 | /// OID value for general-use NIST EC keys held in PKCS#8 and X.509; see RFC 5480 s2.1.1. |
| 23 | const X509_NIST_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.2.1"); |
| 24 | |
| 25 | /// OID value in `AlgorithmIdentifier.parameters` for P-256; see RFC 5480 s2.1.1.1. |
| 26 | const ALGO_PARAM_P256_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7"); |
Alice Wang | 000595b | 2023-10-02 13:46:45 +0000 | [diff] [blame] | 27 | |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 28 | const MESSAGE1: &[u8] = b"test message 1"; |
| 29 | const MESSAGE2: &[u8] = b"test message 2"; |
| 30 | |
Alice Wang | 000595b | 2023-10-02 13:46:45 +0000 | [diff] [blame] | 31 | #[test] |
| 32 | fn ec_private_key_serialization() -> Result<()> { |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 33 | let mut ec_key = EcKey::new_p256()?; |
| 34 | ec_key.generate_key()?; |
Alice Wang | 000595b | 2023-10-02 13:46:45 +0000 | [diff] [blame] | 35 | let der_encoded_ec_private_key = ec_key.ec_private_key()?; |
| 36 | let deserialized_ec_key = EcKey::from_ec_private_key(der_encoded_ec_private_key.as_slice())?; |
| 37 | |
| 38 | assert_eq!(ec_key.cose_public_key()?, deserialized_ec_key.cose_public_key()?); |
| 39 | Ok(()) |
| 40 | } |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 41 | |
| 42 | #[test] |
Alice Wang | 600ea5b | 2023-11-17 15:12:16 +0000 | [diff] [blame] | 43 | fn subject_public_key_info_serialization() -> Result<()> { |
| 44 | let mut ec_key = EcKey::new_p256()?; |
| 45 | ec_key.generate_key()?; |
Alice Wang | eb77f7d | 2023-12-01 09:13:58 +0000 | [diff] [blame] | 46 | let pkey: PKey = ec_key.try_into()?; |
Alice Wang | 600ea5b | 2023-11-17 15:12:16 +0000 | [diff] [blame] | 47 | let subject_public_key_info = pkey.subject_public_key_info()?; |
| 48 | |
Andrew Walbran | 5b879eb | 2023-12-18 13:49:02 +0000 | [diff] [blame^] | 49 | let subject_public_key_info = |
| 50 | SubjectPublicKeyInfoRef::from_der(&subject_public_key_info).unwrap(); |
Alice Wang | 600ea5b | 2023-11-17 15:12:16 +0000 | [diff] [blame] | 51 | let expected_algorithm = AlgorithmIdentifier { |
| 52 | oid: X509_NIST_OID, |
| 53 | parameters: Some(AnyRef::from(&ALGO_PARAM_P256_OID)), |
| 54 | }; |
| 55 | assert_eq!(expected_algorithm, subject_public_key_info.algorithm); |
Andrew Walbran | 5b879eb | 2023-12-18 13:49:02 +0000 | [diff] [blame^] | 56 | assert!(!subject_public_key_info.subject_public_key.to_der().unwrap().is_empty()); |
Alice Wang | 600ea5b | 2023-11-17 15:12:16 +0000 | [diff] [blame] | 57 | Ok(()) |
| 58 | } |
| 59 | |
| 60 | #[test] |
Alice Wang | 306c8e2 | 2023-11-29 12:40:43 +0000 | [diff] [blame] | 61 | fn p256_cose_public_key_serialization() -> Result<()> { |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 62 | let mut ec_key = EcKey::new_p256()?; |
Alice Wang | 306c8e2 | 2023-11-29 12:40:43 +0000 | [diff] [blame] | 63 | check_cose_public_key_serialization(&mut ec_key) |
| 64 | } |
| 65 | |
| 66 | #[test] |
| 67 | fn p384_cose_public_key_serialization() -> Result<()> { |
| 68 | let mut ec_key = EcKey::new_p384()?; |
| 69 | check_cose_public_key_serialization(&mut ec_key) |
| 70 | } |
| 71 | |
| 72 | fn check_cose_public_key_serialization(ec_key: &mut EcKey) -> Result<()> { |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 73 | ec_key.generate_key()?; |
| 74 | let cose_key = ec_key.cose_public_key()?; |
| 75 | let cose_key_data = cose_key.clone().to_vec().unwrap(); |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame] | 76 | let deserialized_ec_key = EcKey::from_cose_public_key_slice(&cose_key_data)?; |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 77 | |
| 78 | assert_eq!(cose_key, deserialized_ec_key.cose_public_key()?); |
| 79 | Ok(()) |
| 80 | } |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 81 | |
| 82 | #[test] |
| 83 | fn ecdsa_p256_signing_and_verification_succeed() -> Result<()> { |
| 84 | let mut ec_key = EcKey::new_p256()?; |
| 85 | ec_key.generate_key()?; |
Alice Wang | 884648d | 2023-12-01 09:50:20 +0000 | [diff] [blame] | 86 | let digester = Digester::sha256(); |
| 87 | let digest = digester.digest(MESSAGE1)?; |
| 88 | assert_eq!(digest, sha256(MESSAGE1)?); |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 89 | |
| 90 | let signature = ec_key.ecdsa_sign(&digest)?; |
Alice Wang | 7468ae4 | 2023-11-30 10:20:36 +0000 | [diff] [blame] | 91 | ec_key.ecdsa_verify(&signature, &digest)?; |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame] | 92 | // Building a `PKey` from a temporary `CoseKey` should work as the lifetime |
| 93 | // of the `PKey` is not tied to the lifetime of the `CoseKey`. |
| 94 | let pkey = PKey::from_cose_public_key(&ec_key.cose_public_key()?)?; |
Alice Wang | 884648d | 2023-12-01 09:50:20 +0000 | [diff] [blame] | 95 | pkey.verify(&signature, MESSAGE1, Some(digester)) |
| 96 | } |
| 97 | |
| 98 | #[test] |
| 99 | fn ecdsa_p384_signing_and_verification_succeed() -> Result<()> { |
| 100 | let mut ec_key = EcKey::new_p384()?; |
| 101 | ec_key.generate_key()?; |
| 102 | let digester = Digester::sha384(); |
| 103 | let digest = digester.digest(MESSAGE1)?; |
| 104 | |
| 105 | let signature = ec_key.ecdsa_sign(&digest)?; |
| 106 | ec_key.ecdsa_verify(&signature, &digest)?; |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame] | 107 | let pkey = PKey::from_cose_public_key(&ec_key.cose_public_key()?)?; |
Alice Wang | 884648d | 2023-12-01 09:50:20 +0000 | [diff] [blame] | 108 | pkey.verify(&signature, MESSAGE1, Some(digester)) |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | #[test] |
| 112 | fn verifying_ecdsa_p256_signed_with_a_different_key_fails() -> Result<()> { |
| 113 | let mut ec_key1 = EcKey::new_p256()?; |
| 114 | ec_key1.generate_key()?; |
| 115 | let digest = sha256(MESSAGE1)?; |
| 116 | let signature = ec_key1.ecdsa_sign(&digest)?; |
| 117 | |
| 118 | let mut ec_key2 = EcKey::new_p256()?; |
| 119 | ec_key2.generate_key()?; |
| 120 | let err = ec_key2.ecdsa_verify(&signature, &digest).unwrap_err(); |
| 121 | let expected_err = Error::CallFailed(ApiName::ECDSA_verify, EcdsaError::BadSignature.into()); |
| 122 | assert_eq!(expected_err, err); |
Alice Wang | 7468ae4 | 2023-11-30 10:20:36 +0000 | [diff] [blame] | 123 | |
| 124 | let pkey: PKey = ec_key2.try_into()?; |
| 125 | let err = pkey.verify(&signature, MESSAGE1, Some(Digester::sha256())).unwrap_err(); |
| 126 | let expected_err = |
| 127 | Error::CallFailed(ApiName::EVP_DigestVerify, EcdsaError::BadSignature.into()); |
| 128 | assert_eq!(expected_err, err); |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 129 | Ok(()) |
| 130 | } |
| 131 | |
| 132 | #[test] |
| 133 | fn verifying_ecdsa_p256_signed_with_a_different_message_fails() -> Result<()> { |
| 134 | let mut ec_key = EcKey::new_p256()?; |
| 135 | ec_key.generate_key()?; |
| 136 | let digest1 = sha256(MESSAGE1)?; |
| 137 | let signature = ec_key.ecdsa_sign(&digest1)?; |
| 138 | let digest2 = sha256(MESSAGE2)?; |
| 139 | |
| 140 | let err = ec_key.ecdsa_verify(&signature, &digest2).unwrap_err(); |
| 141 | let expected_err = Error::CallFailed(ApiName::ECDSA_verify, EcdsaError::BadSignature.into()); |
| 142 | assert_eq!(expected_err, err); |
| 143 | Ok(()) |
| 144 | } |