| // Copyright 2021 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| use super::*; |
| use crate::{cbor::value::Value, iana, iana::WithPrivateRange, util::expect_err, CborSerializable}; |
| use alloc::{borrow::ToOwned, vec}; |
| |
| #[test] |
| fn test_cwt_encode() { |
| let tests = vec![ |
| ( |
| ClaimsSet { |
| issuer: Some("abc".to_owned()), |
| ..Default::default() |
| }, |
| concat!( |
| "a1", // 1-map |
| "01", "63", "616263" // 1 (iss) => 3-tstr |
| ), |
| ), |
| (ClaimsSetBuilder::new().build(), concat!("a0")), |
| ( |
| ClaimsSetBuilder::new() |
| .issuer("aaa".to_owned()) |
| .subject("bb".to_owned()) |
| .audience("c".to_owned()) |
| .expiration_time(Timestamp::WholeSeconds(0x100)) |
| .not_before(Timestamp::WholeSeconds(0x200)) |
| .issued_at(Timestamp::WholeSeconds(0x10)) |
| .cwt_id(vec![1, 2, 3, 4]) |
| .private_claim(-70_000, Value::Integer(0.into())) |
| .build(), |
| concat!( |
| "a8", // 8-map |
| "01", |
| "63", |
| "616161", // 1 (iss) => 3-tstr |
| "02", |
| "62", |
| "6262", // 2 (sub) => 2-tstr |
| "03", |
| "61", |
| "63", // 3 (aud) => 1-tstr |
| "04", |
| "19", |
| "0100", // 4 (exp) => uint |
| "05", |
| "19", |
| "0200", // 5 (nbf) => uint |
| "06", |
| "10", // 6 (iat) => uint |
| "07", |
| "44", |
| "01020304", // 7 => bstr |
| "3a0001116f", |
| "00" // -70000 => uint |
| ), |
| ), |
| ( |
| ClaimsSetBuilder::new() |
| .claim( |
| iana::CwtClaimName::Cnf, |
| Value::Map(vec![(Value::Integer(0.into()), Value::Integer(0.into()))]), |
| ) |
| .build(), |
| concat!( |
| "a1", // 1-map |
| "08", "a1", "00", "00" |
| ), |
| ), |
| ( |
| ClaimsSetBuilder::new() |
| .text_claim("aa".to_owned(), Value::Integer(0.into())) |
| .build(), |
| concat!( |
| "a1", // 1-map |
| "62", "6161", "00", |
| ), |
| ), |
| ( |
| ClaimsSetBuilder::new() |
| .expiration_time(Timestamp::FractionalSeconds(1.5)) |
| .build(), |
| concat!( |
| "a1", // 1-map |
| "04", // 4 (exp) => |
| // Note: ciborium serializes floats as the smallest float type that |
| // will parse back to the original f64! As a result, 1.5 is encoded |
| // as an f16. |
| "f9", "3e00", |
| ), |
| ), |
| ]; |
| for (i, (claims, claims_data)) in tests.iter().enumerate() { |
| let got = claims.clone().to_vec().unwrap(); |
| assert_eq!(*claims_data, hex::encode(&got), "case {}", i); |
| |
| let got = ClaimsSet::from_slice(&got).unwrap(); |
| assert_eq!(*claims, got); |
| } |
| } |
| |
| #[test] |
| fn test_cwt_decode_fail() { |
| let tests = vec![ |
| ( |
| concat!( |
| "81", // 1-arr |
| "01", |
| ), |
| "expected map", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "01", "08", // 1 (iss) => int (invalid value type) |
| ), |
| "expected tstr", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "02", "08", // 2 (sub) => int (invalid value type) |
| ), |
| "expected tstr", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "03", "08", // 3 (aud) => int (invalid value type) |
| ), |
| "expected tstr", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "04", "40", // 4 (exp) => bstr (invalid value type) |
| ), |
| "expected int/float", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "05", "40", // 5 (nbf) => bstr (invalid value type) |
| ), |
| "expected int/float", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "06", "40", // 6 (iat) => bstr (invalid value type) |
| ), |
| "expected int/float", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "07", "01", // 5 (cti) => uint (invalid value type) |
| ), |
| "expected bstr", |
| ), |
| ( |
| concat!( |
| "a1", // 1-map |
| "07", "40", // 5 (cti) => 0-bstr |
| "06", "01", // 6 (iat) => 1 |
| ), |
| "extraneous data", |
| ), |
| ( |
| concat!( |
| "a2", // 1-map |
| "07", "40", // 5 (cti) => 0-bstr |
| "07", "40", // 5 (cti) => 0-bstr |
| ), |
| "duplicate map key", |
| ), |
| ]; |
| for (claims_data, err_msg) in tests.iter() { |
| let data = hex::decode(claims_data).unwrap(); |
| let result = ClaimsSet::from_slice(&data); |
| expect_err(result, err_msg); |
| } |
| } |
| |
| #[test] |
| fn test_cwt_is_private() { |
| assert!(!iana::CwtClaimName::is_private(1)); |
| assert!(iana::CwtClaimName::is_private(-500_000)); |
| } |
| |
| #[test] |
| #[should_panic] |
| fn test_cwt_claims_builder_core_param_panic() { |
| // Attempting to set a core claim (in range [1,7]) via `.claim()` panics. |
| let _claims = ClaimsSetBuilder::new() |
| .claim(iana::CwtClaimName::Iss, Value::Null) |
| .build(); |
| } |
| |
| #[test] |
| #[should_panic] |
| fn test_cwt_claims_builder_non_private_panic() { |
| // Attempting to set a claim outside of private range via `.private_claim()` panics. |
| let _claims = ClaimsSetBuilder::new() |
| .private_claim(100, Value::Null) |
| .build(); |
| } |
| |
| #[test] |
| fn test_cwt_dup_claim() { |
| // Set a duplicate map key. |
| let claims = ClaimsSetBuilder::new() |
| .claim(iana::CwtClaimName::AceProfile, Value::Integer(1.into())) |
| .claim(iana::CwtClaimName::AceProfile, Value::Integer(2.into())) |
| .build(); |
| // Encoding succeeds. |
| let data = claims.to_vec().unwrap(); |
| // But an attempt to parse the encoded data fails. |
| let result = ClaimsSet::from_slice(&data); |
| expect_err(result, "duplicate map key"); |
| } |