1 // Copyright 2021 Google LLC
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 //
15 ////////////////////////////////////////////////////////////////////////////////
16
17 use super::*;
18 use crate::{cbor::value::Value, iana, iana::WithPrivateRange, util::expect_err, CborSerializable};
19 use alloc::{borrow::ToOwned, vec};
20
21 #[test]
test_cwt_encode()22 fn test_cwt_encode() {
23 let tests = vec![
24 (
25 ClaimsSet {
26 issuer: Some("abc".to_owned()),
27 ..Default::default()
28 },
29 concat!(
30 "a1", // 1-map
31 "01", "63", "616263" // 1 (iss) => 3-tstr
32 ),
33 ),
34 (ClaimsSetBuilder::new().build(), concat!("a0")),
35 (
36 ClaimsSetBuilder::new()
37 .issuer("aaa".to_owned())
38 .subject("bb".to_owned())
39 .audience("c".to_owned())
40 .expiration_time(Timestamp::WholeSeconds(0x100))
41 .not_before(Timestamp::WholeSeconds(0x200))
42 .issued_at(Timestamp::WholeSeconds(0x10))
43 .cwt_id(vec![1, 2, 3, 4])
44 .private_claim(-70_000, Value::Integer(0.into()))
45 .build(),
46 concat!(
47 "a8", // 8-map
48 "01",
49 "63",
50 "616161", // 1 (iss) => 3-tstr
51 "02",
52 "62",
53 "6262", // 2 (sub) => 2-tstr
54 "03",
55 "61",
56 "63", // 3 (aud) => 1-tstr
57 "04",
58 "19",
59 "0100", // 4 (exp) => uint
60 "05",
61 "19",
62 "0200", // 5 (nbf) => uint
63 "06",
64 "10", // 6 (iat) => uint
65 "07",
66 "44",
67 "01020304", // 7 => bstr
68 "3a0001116f",
69 "00" // -70000 => uint
70 ),
71 ),
72 (
73 ClaimsSetBuilder::new()
74 .claim(
75 iana::CwtClaimName::Cnf,
76 Value::Map(vec![(Value::Integer(0.into()), Value::Integer(0.into()))]),
77 )
78 .build(),
79 concat!(
80 "a1", // 1-map
81 "08", "a1", "00", "00"
82 ),
83 ),
84 (
85 ClaimsSetBuilder::new()
86 .text_claim("aa".to_owned(), Value::Integer(0.into()))
87 .build(),
88 concat!(
89 "a1", // 1-map
90 "62", "6161", "00",
91 ),
92 ),
93 (
94 ClaimsSetBuilder::new()
95 .expiration_time(Timestamp::FractionalSeconds(1.5))
96 .build(),
97 concat!(
98 "a1", // 1-map
99 "04", // 4 (exp) =>
100 // Note: ciborium serializes floats as the smallest float type that
101 // will parse back to the original f64! As a result, 1.5 is encoded
102 // as an f16.
103 "f9", "3e00",
104 ),
105 ),
106 ];
107 for (i, (claims, claims_data)) in tests.iter().enumerate() {
108 let got = claims.clone().to_vec().unwrap();
109 assert_eq!(*claims_data, hex::encode(&got), "case {}", i);
110
111 let got = ClaimsSet::from_slice(&got).unwrap();
112 assert_eq!(*claims, got);
113 }
114 }
115
116 #[test]
test_cwt_decode_fail()117 fn test_cwt_decode_fail() {
118 let tests = vec![
119 (
120 concat!(
121 "81", // 1-arr
122 "01",
123 ),
124 "expected map",
125 ),
126 (
127 concat!(
128 "a1", // 1-map
129 "01", "08", // 1 (iss) => int (invalid value type)
130 ),
131 "expected tstr",
132 ),
133 (
134 concat!(
135 "a1", // 1-map
136 "02", "08", // 2 (sub) => int (invalid value type)
137 ),
138 "expected tstr",
139 ),
140 (
141 concat!(
142 "a1", // 1-map
143 "03", "08", // 3 (aud) => int (invalid value type)
144 ),
145 "expected tstr",
146 ),
147 (
148 concat!(
149 "a1", // 1-map
150 "04", "40", // 4 (exp) => bstr (invalid value type)
151 ),
152 "expected int/float",
153 ),
154 (
155 concat!(
156 "a1", // 1-map
157 "05", "40", // 5 (nbf) => bstr (invalid value type)
158 ),
159 "expected int/float",
160 ),
161 (
162 concat!(
163 "a1", // 1-map
164 "06", "40", // 6 (iat) => bstr (invalid value type)
165 ),
166 "expected int/float",
167 ),
168 (
169 concat!(
170 "a1", // 1-map
171 "07", "01", // 5 (cti) => uint (invalid value type)
172 ),
173 "expected bstr",
174 ),
175 (
176 concat!(
177 "a1", // 1-map
178 "07", "40", // 5 (cti) => 0-bstr
179 "06", "01", // 6 (iat) => 1
180 ),
181 "extraneous data",
182 ),
183 (
184 concat!(
185 "a2", // 1-map
186 "07", "40", // 5 (cti) => 0-bstr
187 "07", "40", // 5 (cti) => 0-bstr
188 ),
189 "duplicate map key",
190 ),
191 ];
192 for (claims_data, err_msg) in tests.iter() {
193 let data = hex::decode(claims_data).unwrap();
194 let result = ClaimsSet::from_slice(&data);
195 expect_err(result, err_msg);
196 }
197 }
198
199 #[test]
test_cwt_is_private()200 fn test_cwt_is_private() {
201 assert!(!iana::CwtClaimName::is_private(1));
202 assert!(iana::CwtClaimName::is_private(-500_000));
203 }
204
205 #[test]
206 #[should_panic]
test_cwt_claims_builder_core_param_panic()207 fn test_cwt_claims_builder_core_param_panic() {
208 // Attempting to set a core claim (in range [1,7]) via `.claim()` panics.
209 let _claims = ClaimsSetBuilder::new()
210 .claim(iana::CwtClaimName::Iss, Value::Null)
211 .build();
212 }
213
214 #[test]
215 #[should_panic]
test_cwt_claims_builder_non_private_panic()216 fn test_cwt_claims_builder_non_private_panic() {
217 // Attempting to set a claim outside of private range via `.private_claim()` panics.
218 let _claims = ClaimsSetBuilder::new()
219 .private_claim(100, Value::Null)
220 .build();
221 }
222
223 #[test]
test_cwt_dup_claim()224 fn test_cwt_dup_claim() {
225 // Set a duplicate map key.
226 let claims = ClaimsSetBuilder::new()
227 .claim(iana::CwtClaimName::AceProfile, Value::Integer(1.into()))
228 .claim(iana::CwtClaimName::AceProfile, Value::Integer(2.into()))
229 .build();
230 // Encoding succeeds.
231 let data = claims.to_vec().unwrap();
232 // But an attempt to parse the encoded data fails.
233 let result = ClaimsSet::from_slice(&data);
234 expect_err(result, "duplicate map key");
235 }
236