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::{ |
| 18 | der::{AnyRef, Decode}, |
| 19 | AlgorithmIdentifier, ObjectIdentifier, SubjectPublicKeyInfo, |
| 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 | |
| 49 | let subject_public_key_info = SubjectPublicKeyInfo::from_der(&subject_public_key_info).unwrap(); |
| 50 | let expected_algorithm = AlgorithmIdentifier { |
| 51 | oid: X509_NIST_OID, |
| 52 | parameters: Some(AnyRef::from(&ALGO_PARAM_P256_OID)), |
| 53 | }; |
| 54 | assert_eq!(expected_algorithm, subject_public_key_info.algorithm); |
| 55 | assert!(!subject_public_key_info.subject_public_key.to_vec().is_empty()); |
| 56 | Ok(()) |
| 57 | } |
| 58 | |
| 59 | #[test] |
Alice Wang | 306c8e2 | 2023-11-29 12:40:43 +0000 | [diff] [blame] | 60 | fn p256_cose_public_key_serialization() -> Result<()> { |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 61 | let mut ec_key = EcKey::new_p256()?; |
Alice Wang | 306c8e2 | 2023-11-29 12:40:43 +0000 | [diff] [blame] | 62 | check_cose_public_key_serialization(&mut ec_key) |
| 63 | } |
| 64 | |
| 65 | #[test] |
| 66 | fn p384_cose_public_key_serialization() -> Result<()> { |
| 67 | let mut ec_key = EcKey::new_p384()?; |
| 68 | check_cose_public_key_serialization(&mut ec_key) |
| 69 | } |
| 70 | |
| 71 | fn check_cose_public_key_serialization(ec_key: &mut EcKey) -> Result<()> { |
Alice Wang | 9bd9809 | 2023-11-10 14:08:12 +0000 | [diff] [blame] | 72 | ec_key.generate_key()?; |
| 73 | let cose_key = ec_key.cose_public_key()?; |
| 74 | let cose_key_data = cose_key.clone().to_vec().unwrap(); |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame^] | 75 | 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] | 76 | |
| 77 | assert_eq!(cose_key, deserialized_ec_key.cose_public_key()?); |
| 78 | Ok(()) |
| 79 | } |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 80 | |
| 81 | #[test] |
| 82 | fn ecdsa_p256_signing_and_verification_succeed() -> Result<()> { |
| 83 | let mut ec_key = EcKey::new_p256()?; |
| 84 | ec_key.generate_key()?; |
Alice Wang | 884648d | 2023-12-01 09:50:20 +0000 | [diff] [blame] | 85 | let digester = Digester::sha256(); |
| 86 | let digest = digester.digest(MESSAGE1)?; |
| 87 | assert_eq!(digest, sha256(MESSAGE1)?); |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 88 | |
| 89 | let signature = ec_key.ecdsa_sign(&digest)?; |
Alice Wang | 7468ae4 | 2023-11-30 10:20:36 +0000 | [diff] [blame] | 90 | ec_key.ecdsa_verify(&signature, &digest)?; |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame^] | 91 | // Building a `PKey` from a temporary `CoseKey` should work as the lifetime |
| 92 | // of the `PKey` is not tied to the lifetime of the `CoseKey`. |
| 93 | let pkey = PKey::from_cose_public_key(&ec_key.cose_public_key()?)?; |
Alice Wang | 884648d | 2023-12-01 09:50:20 +0000 | [diff] [blame] | 94 | pkey.verify(&signature, MESSAGE1, Some(digester)) |
| 95 | } |
| 96 | |
| 97 | #[test] |
| 98 | fn ecdsa_p384_signing_and_verification_succeed() -> Result<()> { |
| 99 | let mut ec_key = EcKey::new_p384()?; |
| 100 | ec_key.generate_key()?; |
| 101 | let digester = Digester::sha384(); |
| 102 | let digest = digester.digest(MESSAGE1)?; |
| 103 | |
| 104 | let signature = ec_key.ecdsa_sign(&digest)?; |
| 105 | ec_key.ecdsa_verify(&signature, &digest)?; |
Alice Wang | be7a4b1 | 2023-12-01 11:53:36 +0000 | [diff] [blame^] | 106 | let pkey = PKey::from_cose_public_key(&ec_key.cose_public_key()?)?; |
Alice Wang | 884648d | 2023-12-01 09:50:20 +0000 | [diff] [blame] | 107 | pkey.verify(&signature, MESSAGE1, Some(digester)) |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 108 | } |
| 109 | |
| 110 | #[test] |
| 111 | fn verifying_ecdsa_p256_signed_with_a_different_key_fails() -> Result<()> { |
| 112 | let mut ec_key1 = EcKey::new_p256()?; |
| 113 | ec_key1.generate_key()?; |
| 114 | let digest = sha256(MESSAGE1)?; |
| 115 | let signature = ec_key1.ecdsa_sign(&digest)?; |
| 116 | |
| 117 | let mut ec_key2 = EcKey::new_p256()?; |
| 118 | ec_key2.generate_key()?; |
| 119 | let err = ec_key2.ecdsa_verify(&signature, &digest).unwrap_err(); |
| 120 | let expected_err = Error::CallFailed(ApiName::ECDSA_verify, EcdsaError::BadSignature.into()); |
| 121 | assert_eq!(expected_err, err); |
Alice Wang | 7468ae4 | 2023-11-30 10:20:36 +0000 | [diff] [blame] | 122 | |
| 123 | let pkey: PKey = ec_key2.try_into()?; |
| 124 | let err = pkey.verify(&signature, MESSAGE1, Some(Digester::sha256())).unwrap_err(); |
| 125 | let expected_err = |
| 126 | Error::CallFailed(ApiName::EVP_DigestVerify, EcdsaError::BadSignature.into()); |
| 127 | assert_eq!(expected_err, err); |
Alice Wang | 0271ee0 | 2023-11-15 15:03:42 +0000 | [diff] [blame] | 128 | Ok(()) |
| 129 | } |
| 130 | |
| 131 | #[test] |
| 132 | fn verifying_ecdsa_p256_signed_with_a_different_message_fails() -> Result<()> { |
| 133 | let mut ec_key = EcKey::new_p256()?; |
| 134 | ec_key.generate_key()?; |
| 135 | let digest1 = sha256(MESSAGE1)?; |
| 136 | let signature = ec_key.ecdsa_sign(&digest1)?; |
| 137 | let digest2 = sha256(MESSAGE2)?; |
| 138 | |
| 139 | let err = ec_key.ecdsa_verify(&signature, &digest2).unwrap_err(); |
| 140 | let expected_err = Error::CallFailed(ApiName::ECDSA_verify, EcdsaError::BadSignature.into()); |
| 141 | assert_eq!(expected_err, err); |
| 142 | Ok(()) |
| 143 | } |