1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #[cfg(test)] 18 mod tests { 19 use diced_open_dice::{ 20 derive_cdi_certificate_id, derive_cdi_private_key_seed, hash, kdf, keypair_from_seed, 21 retry_sign_cose_sign1, retry_sign_cose_sign1_with_cdi_leaf_priv, sign, verify, 22 DiceArtifacts, PrivateKey, CDI_SIZE, HASH_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE, 23 }; 24 #[cfg(feature = "multialg")] 25 use diced_open_dice::{ 26 keypair_from_seed_multialg, retry_sign_cose_sign1_multialg, 27 retry_sign_cose_sign1_with_cdi_leaf_priv_multialg, verify_multialg, KeyAlgorithm, 28 }; 29 30 use coset::{CborSerializable, CoseSign1}; 31 32 // This test initialization is only required for the trusty test harness. 33 #[cfg(feature = "trusty")] 34 test::init!(); 35 36 #[test] hash_succeeds()37 fn hash_succeeds() { 38 const EXPECTED_HASH: [u8; HASH_SIZE] = [ 39 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02, 40 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8, 41 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda, 42 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d, 43 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f, 44 ]; 45 assert_eq!(EXPECTED_HASH, hash(b"hello world").expect("hash failed")); 46 } 47 48 #[test] kdf_succeeds()49 fn kdf_succeeds() { 50 let mut derived_key = [0u8; PRIVATE_KEY_SEED_SIZE]; 51 kdf(b"myInitialKeyMaterial", b"mySalt", b"myInfo", &mut derived_key).unwrap(); 52 const EXPECTED_DERIVED_KEY: [u8; PRIVATE_KEY_SEED_SIZE] = [ 53 0x91, 0x9b, 0x8d, 0x29, 0xc4, 0x1b, 0x93, 0xd7, 0xeb, 0x09, 0xfa, 0xd7, 0xc9, 0x87, 54 0xb0, 0xd1, 0xcc, 0x26, 0xef, 0x07, 0x83, 0x42, 0xcf, 0xa3, 0x45, 0x0a, 0x57, 0xe9, 55 0x19, 0x86, 0xef, 0x48, 56 ]; 57 assert_eq!(EXPECTED_DERIVED_KEY, derived_key); 58 } 59 60 #[test] derive_cdi_certificate_id_succeeds()61 fn derive_cdi_certificate_id_succeeds() { 62 const EXPECTED_ID: [u8; ID_SIZE] = [ 63 0x7a, 0x36, 0x45, 0x2c, 0x02, 0xf6, 0x2b, 0xec, 0xf9, 0x80, 0x06, 0x75, 0x87, 0xa5, 64 0xc1, 0x44, 0x0c, 0xd3, 0xc0, 0x6d, 65 ]; 66 assert_eq!(EXPECTED_ID, derive_cdi_certificate_id(b"MyPubKey").unwrap()); 67 } 68 69 const EXPECTED_SEED: &[u8] = &[ 70 0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba, 71 0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5, 72 0x3a, 0x08, 0x84, 0x8a, 0x98, 0x85, 0x6d, 0xf5, 0x69, 0x21, 0x03, 0xcd, 0x09, 0xc3, 0x28, 73 0xd6, 0x06, 0xa7, 0x57, 0xbd, 0x48, 0x4b, 0x0f, 0x79, 0x0f, 0xf8, 0x2f, 0xf0, 0x0a, 0x41, 74 0x94, 0xd8, 0x8c, 0xa8, 75 ]; 76 77 const EXPECTED_CDI_ATTEST: &[u8; CDI_SIZE] = &[ 78 0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba, 79 0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5, 80 0x3a, 0x08, 81 ]; 82 83 const EXPECTED_CDI_PRIVATE_KEY_SEED: &[u8] = &[ 84 0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe, 85 0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72, 86 0x02, 0x6e, 87 ]; 88 89 const EXPECTED_PUB_KEY: &[u8] = &[ 90 0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23, 91 0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61, 92 0x06, 0x37, 93 ]; 94 const EXPECTED_PRIV_KEY: &[u8] = &[ 95 0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe, 96 0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72, 97 0x02, 0x6e, 0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 98 0xfc, 0x23, 0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 99 0xf1, 0x61, 0x06, 0x37, 100 ]; 101 #[cfg(feature = "multialg")] 102 const EXPECTED_EC_P256_PUB_KEY: &[u8] = &[ 103 0xa7, 0x93, 0x70, 0x16, 0xff, 0xe8, 0x3c, 0x23, 0x5f, 0x6b, 0xf9, 0x38, 0x7e, 0x9c, 0xe5, 104 0x21, 0xb5, 0x8a, 0x9b, 0x68, 0x5a, 0x2f, 0x62, 0xf4, 0x15, 0x94, 0x1c, 0x61, 0xb3, 0xbb, 105 0xe1, 0x26, 0x61, 0x47, 0x97, 0xbf, 0x3a, 0x1f, 0x6b, 0x87, 0x86, 0x47, 0x5e, 0xc3, 0xa6, 106 0x8b, 0x95, 0x89, 0x9e, 0x29, 0xd5, 0x55, 0x2a, 0xdd, 0x2a, 0x3f, 0xe5, 0xf0, 0x7a, 0xd6, 107 0xc4, 0x7b, 0x64, 0xe0, 108 ]; 109 #[cfg(feature = "multialg")] 110 const EXPECTED_EC_P256_PRIV_KEY: &[u8] = &[ 111 0x62, 0x32, 0x1b, 0xb, 0x5c, 0xac, 0x8f, 0x20, 0x61, 0xb7, 0xa3, 0xbb, 0x46, 0x2b, 0x4e, 112 0xb3, 0x3f, 0xa7, 0xf6, 0x9b, 0x2f, 0x5b, 0x80, 0xa8, 0x55, 0x5e, 0x80, 0x26, 0xbb, 0x72, 113 0xbe, 0xe7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 114 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 115 ]; 116 const EXPECTED_SIGNATURE: &[u8] = &[ 117 0x44, 0xae, 0xcc, 0xe2, 0xb9, 0x96, 0x18, 0x39, 0x0e, 0x61, 0x0f, 0x53, 0x07, 0xbf, 0xf2, 118 0x32, 0x3d, 0x44, 0xd4, 0xf2, 0x07, 0x23, 0x30, 0x85, 0x32, 0x18, 0xd2, 0x69, 0xb8, 0x29, 119 0x3c, 0x26, 0xe6, 0x0d, 0x9c, 0xa5, 0xc2, 0x73, 0xcd, 0x8c, 0xb8, 0x3c, 0x3e, 0x5b, 0xfd, 120 0x62, 0x8d, 0xf6, 0xc4, 0x27, 0xa6, 0xe9, 0x11, 0x06, 0x5a, 0xb2, 0x2b, 0x64, 0xf7, 0xfc, 121 0xbb, 0xab, 0x4a, 0x0e, 122 ]; 123 124 #[test] hash_derive_sign_verify()125 fn hash_derive_sign_verify() { 126 let (pub_key, priv_key) = get_test_key_pair(); 127 128 let mut signature = sign(b"MyMessage", priv_key.as_array()).unwrap(); 129 assert_eq!(&signature, EXPECTED_SIGNATURE); 130 assert!(verify(b"MyMessage", &signature, &pub_key).is_ok()); 131 assert!(verify(b"MyMessage_fail", &signature, &pub_key).is_err()); 132 signature[0] += 1; 133 assert!(verify(b"MyMessage", &signature, &pub_key).is_err()); 134 } 135 136 #[test] sign_cose_sign1_verify()137 fn sign_cose_sign1_verify() { 138 let (pub_key, priv_key) = get_test_key_pair(); 139 140 let signature_res = retry_sign_cose_sign1(b"MyMessage", b"MyAad", priv_key.as_array()); 141 assert!(signature_res.is_ok()); 142 let signature = signature_res.unwrap(); 143 let cose_sign1_res = CoseSign1::from_slice(&signature); 144 assert!(cose_sign1_res.is_ok()); 145 let mut cose_sign1 = cose_sign1_res.unwrap(); 146 147 let mut verify_result = 148 cose_sign1.verify_signature(b"MyAad", |sign, data| verify(data, sign, &pub_key)); 149 assert!(verify_result.is_ok()); 150 151 verify_result = 152 cose_sign1.verify_signature(b"BadAad", |sign, data| verify(data, sign, &pub_key)); 153 assert!(verify_result.is_err()); 154 155 // if we modify the signature, the payload should no longer verify 156 cose_sign1.signature.push(0xAA); 157 verify_result = 158 cose_sign1.verify_signature(b"MyAad", |sign, data| verify(data, sign, &pub_key)); 159 assert!(verify_result.is_err()); 160 } 161 162 #[cfg(feature = "multialg")] 163 #[test] sign_cose_sign1_verify_multialg()164 fn sign_cose_sign1_verify_multialg() { 165 let (pub_key, priv_key) = get_test_key_pair_ec_p256(); 166 167 let signature_res = retry_sign_cose_sign1_multialg( 168 b"MyMessage", 169 b"MyAad", 170 priv_key.as_array(), 171 KeyAlgorithm::EcdsaP256, 172 ); 173 assert!(signature_res.is_ok()); 174 let signature = signature_res.unwrap(); 175 let cose_sign1_res = CoseSign1::from_slice(&signature); 176 assert!(cose_sign1_res.is_ok()); 177 let mut cose_sign1 = cose_sign1_res.unwrap(); 178 179 let mut verify_result = cose_sign1.verify_signature(b"MyAad", |sign, data| { 180 verify_multialg(data, sign, &pub_key, KeyAlgorithm::EcdsaP256) 181 }); 182 assert!(verify_result.is_ok()); 183 184 verify_result = cose_sign1.verify_signature(b"BadAad", |sign, data| { 185 verify_multialg(data, sign, &pub_key, KeyAlgorithm::EcdsaP256) 186 }); 187 assert!(verify_result.is_err()); 188 189 // if we modify the signature, the payload should no longer verify 190 cose_sign1.signature.push(0xAA); 191 verify_result = cose_sign1.verify_signature(b"MyAad", |sign, data| { 192 verify_multialg(data, sign, &pub_key, KeyAlgorithm::EcdsaP256) 193 }); 194 assert!(verify_result.is_err()); 195 } 196 197 struct TestArtifactsForSigning {} 198 199 impl DiceArtifacts for TestArtifactsForSigning { cdi_attest(&self) -> &[u8; CDI_SIZE]200 fn cdi_attest(&self) -> &[u8; CDI_SIZE] { 201 EXPECTED_CDI_ATTEST 202 } 203 cdi_seal(&self) -> &[u8; CDI_SIZE]204 fn cdi_seal(&self) -> &[u8; CDI_SIZE] { 205 unimplemented!("no test functionality depends on this") 206 } 207 bcc(&self) -> Option<&[u8]>208 fn bcc(&self) -> Option<&[u8]> { 209 unimplemented!("no test functionality depends on this") 210 } 211 } 212 213 #[test] sign_cose_sign1_with_cdi_leaf_priv_verify()214 fn sign_cose_sign1_with_cdi_leaf_priv_verify() { 215 let dice = TestArtifactsForSigning {}; 216 217 let signature_res = retry_sign_cose_sign1_with_cdi_leaf_priv(b"MyMessage", b"MyAad", &dice); 218 assert!(signature_res.is_ok()); 219 let signature = signature_res.unwrap(); 220 let cose_sign1_res = CoseSign1::from_slice(&signature); 221 assert!(cose_sign1_res.is_ok()); 222 let mut cose_sign1 = cose_sign1_res.unwrap(); 223 224 let mut verify_result = cose_sign1 225 .verify_signature(b"MyAad", |sign, data| verify(data, sign, EXPECTED_PUB_KEY)); 226 assert!(verify_result.is_ok()); 227 228 verify_result = cose_sign1 229 .verify_signature(b"BadAad", |sign, data| verify(data, sign, EXPECTED_PUB_KEY)); 230 assert!(verify_result.is_err()); 231 232 // if we modify the signature, the payload should no longer verify 233 cose_sign1.signature.push(0xAA); 234 verify_result = cose_sign1 235 .verify_signature(b"MyAad", |sign, data| verify(data, sign, EXPECTED_PUB_KEY)); 236 assert!(verify_result.is_err()); 237 } 238 239 #[cfg(feature = "multialg")] 240 #[test] sign_cose_sign1_with_cdi_leaf_priv_verify_multialg()241 fn sign_cose_sign1_with_cdi_leaf_priv_verify_multialg() { 242 let dice = TestArtifactsForSigning {}; 243 244 let signature_res = retry_sign_cose_sign1_with_cdi_leaf_priv_multialg( 245 b"MyMessage", 246 b"MyAad", 247 &dice, 248 KeyAlgorithm::EcdsaP256, 249 ); 250 assert!(signature_res.is_ok()); 251 let signature = signature_res.unwrap(); 252 let cose_sign1_res = CoseSign1::from_slice(&signature); 253 assert!(cose_sign1_res.is_ok()); 254 let mut cose_sign1 = cose_sign1_res.unwrap(); 255 256 let mut verify_result = cose_sign1.verify_signature(b"MyAad", |sign, data| { 257 verify_multialg(data, sign, EXPECTED_EC_P256_PUB_KEY, KeyAlgorithm::EcdsaP256) 258 }); 259 assert!(verify_result.is_ok()); 260 261 verify_result = cose_sign1.verify_signature(b"BadAad", |sign, data| { 262 verify_multialg(data, sign, EXPECTED_EC_P256_PUB_KEY, KeyAlgorithm::EcdsaP256) 263 }); 264 assert!(verify_result.is_err()); 265 266 // if we modify the signature, the payload should no longer verify 267 cose_sign1.signature.push(0xAA); 268 verify_result = cose_sign1.verify_signature(b"MyAad", |sign, data| { 269 verify_multialg(data, sign, EXPECTED_EC_P256_PUB_KEY, KeyAlgorithm::EcdsaP256) 270 }); 271 assert!(verify_result.is_err()); 272 } 273 get_test_key_pair() -> (Vec<u8>, PrivateKey)274 fn get_test_key_pair() -> (Vec<u8>, PrivateKey) { 275 let seed = hash(b"MySeedString").unwrap(); 276 assert_eq!(seed, EXPECTED_SEED); 277 let cdi_attest = &seed[..CDI_SIZE]; 278 assert_eq!(cdi_attest, EXPECTED_CDI_ATTEST); 279 let cdi_private_key_seed = 280 derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap(); 281 assert_eq!(cdi_private_key_seed.as_array(), EXPECTED_CDI_PRIVATE_KEY_SEED); 282 let (pub_key, priv_key) = keypair_from_seed(cdi_private_key_seed.as_array()).unwrap(); 283 assert_eq!(&pub_key, EXPECTED_PUB_KEY); 284 assert_eq!(priv_key.as_array(), EXPECTED_PRIV_KEY); 285 286 (pub_key, priv_key) 287 } 288 289 #[cfg(feature = "multialg")] get_test_key_pair_ec_p256() -> (Vec<u8>, PrivateKey)290 fn get_test_key_pair_ec_p256() -> (Vec<u8>, PrivateKey) { 291 let seed = hash(b"MySeedString").unwrap(); 292 assert_eq!(seed, EXPECTED_SEED); 293 let cdi_attest = &seed[..CDI_SIZE]; 294 assert_eq!(cdi_attest, EXPECTED_CDI_ATTEST); 295 let cdi_private_key_seed = 296 derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap(); 297 assert_eq!(cdi_private_key_seed.as_array(), EXPECTED_CDI_PRIVATE_KEY_SEED); 298 let (pub_key, priv_key) = 299 keypair_from_seed_multialg(cdi_private_key_seed.as_array(), KeyAlgorithm::EcdsaP256) 300 .unwrap(); 301 302 assert_eq!(&pub_key, EXPECTED_EC_P256_PUB_KEY); 303 assert_eq!(priv_key.as_array(), EXPECTED_EC_P256_PRIV_KEY); 304 305 (pub_key, priv_key) 306 } 307 } 308