@@ -7,7 +7,10 @@ use bitmask::*;
77use ciborium:: de:: from_reader;
88use ciborium:: Value ;
99
10+ pub const REALM_PROFILE : & str = "tag:arm.com,2023:realm#1.0.0" ;
11+
1012const REALM_CHALLENGE_LABEL : i128 = 10 ;
13+ const REALM_PROFILE_LABEL : i128 = 265 ;
1114const REALM_PERSO_LABEL : i128 = 44235 ;
1215const REALM_RIM_LABEL : i128 = 44238 ;
1316const REALM_REM_LABEL : i128 = 44239 ;
@@ -25,6 +28,7 @@ bitmask! {
2528 HashAlg = 0x10 ,
2629 Rak = 0x20 ,
2730 RakHashAlg = 0x40 ,
31+ Profile = 0x80 ,
2832 }
2933}
3034
@@ -33,11 +37,13 @@ bitmask! {
3337#[ derive( Debug ) ]
3438pub struct Realm {
3539 pub challenge : [ u8 ; 64 ] , // 10 => bytes .size 64
40+ pub profile : String , // 265 => text
3641 pub perso : [ u8 ; 64 ] , // 44235 => bytes .size 64
3742 pub rim : Vec < u8 > , // 44238 => bytes .size {32,48,64}
3843 pub rem : [ Vec < u8 > ; 4 ] , // 44239 => [ 4*4 bytes .size {32,48,64} ]
3944 pub hash_alg : String , // 44236 => text
40- pub rak : [ u8 ; 97 ] , // 44237 => bytes .size 97
45+ pub raw_rak : [ u8 ; 97 ] , // 44237 => bytes .size 97 (profile=="")
46+ pub cose_rak : Vec < u8 > , // 44237 => bytes .cbor COSE_Key (profile==REALM_PROFILE)
4147 pub rak_hash_alg : String , // 44240 => text
4248
4349 claims_set : ClaimsSet ,
@@ -53,11 +59,13 @@ impl Realm {
5359 pub fn new ( ) -> Self {
5460 Self {
5561 challenge : [ 0 ; 64 ] ,
62+ profile : String :: from ( "" ) ,
5663 perso : [ 0 ; 64 ] ,
5764 rim : vec ! [ 0 , 64 ] ,
5865 rem : Default :: default ( ) ,
5966 hash_alg : String :: from ( "" ) ,
60- rak : [ 0 ; 97 ] ,
67+ raw_rak : [ 0 ; 97 ] ,
68+ cose_rak : Default :: default ( ) ,
6169 rak_hash_alg : String :: from ( "" ) ,
6270 claims_set : ClaimsSet :: none ( ) ,
6371 }
@@ -81,6 +89,17 @@ impl Realm {
8189 }
8290
8391 fn parse ( & mut self , contents : Vec < ( Value , Value ) > ) -> Result < ( ) , Error > {
92+ // Extract the profile claim first. This is because the RAK claim
93+ // (44237) has different encodings depending on the profile value.
94+ for ( k, v) in contents. iter ( ) {
95+ if let Value :: Integer ( i) = k {
96+ match ( * i) . into ( ) {
97+ REALM_PROFILE_LABEL => self . set_profile ( v) ?,
98+ _ => continue ,
99+ }
100+ }
101+ }
102+
84103 for ( k, v) in contents. iter ( ) {
85104 if let Value :: Integer ( i) = k {
86105 match ( * i) . into ( ) {
@@ -98,6 +117,7 @@ impl Realm {
98117 continue ;
99118 }
100119 }
120+
101121 Ok ( ( ) )
102122 }
103123
@@ -119,11 +139,38 @@ impl Realm {
119139 }
120140 }
121141
142+ // RAK format depends on the token profile
143+ if self . profile == REALM_PROFILE {
144+ if self . cose_rak . is_empty ( ) {
145+ return Err ( Error :: Sema ( "RAK COSE_Key not set" . to_string ( ) ) ) ;
146+ }
147+ } else if self . raw_rak == [ 0 ; 97 ] {
148+ return Err ( Error :: Sema ( "RAK raw public key not set" . to_string ( ) ) ) ;
149+ }
150+
122151 // TODO: hash-type'd measurements are compatible with hash-alg
123152
124153 Ok ( ( ) )
125154 }
126155
156+ fn set_profile ( & mut self , v : & Value ) -> Result < ( ) , Error > {
157+ if self . claims_set . contains ( Claims :: Profile ) {
158+ return Err ( Error :: DuplicatedClaim ( "profile" . to_string ( ) ) ) ;
159+ }
160+
161+ let p = to_tstr ( v, "profile" ) ?;
162+
163+ if p != REALM_PROFILE {
164+ return Err ( Error :: UnknownProfile ( p. to_string ( ) ) ) ;
165+ }
166+
167+ self . profile = p;
168+
169+ self . claims_set . set ( Claims :: Profile ) ;
170+
171+ Ok ( ( ) )
172+ }
173+
127174 fn set_challenge ( & mut self , v : & Value ) -> Result < ( ) , Error > {
128175 if self . claims_set . contains ( Claims :: Challenge ) {
129176 return Err ( Error :: DuplicatedClaim ( "challenge" . to_string ( ) ) ) ;
@@ -203,15 +250,19 @@ impl Realm {
203250 let x = v. as_bytes ( ) . unwrap ( ) . clone ( ) ;
204251 let x_len = x. len ( ) ;
205252
206- if x_len != 97 {
207- return Err ( Error :: Sema ( format ! (
208- "public-key: expecting 97 bytes, got {}" ,
209- x_len
210- ) ) ) ;
253+ // Backwards compatibility with the previous "raw key" format.
254+ if self . profile . is_empty ( ) {
255+ if x_len != 97 {
256+ return Err ( Error :: Sema ( format ! (
257+ "public-key: expecting 97 bytes, got {}" ,
258+ x_len
259+ ) ) ) ;
260+ }
261+ self . raw_rak [ ..] . clone_from_slice ( & x) ;
262+ } else {
263+ self . cose_rak = x
211264 }
212265
213- self . rak [ ..] . clone_from_slice ( & x) ;
214-
215266 self . claims_set . set ( Claims :: Rak ) ;
216267
217268 Ok ( ( ) )
@@ -279,19 +330,28 @@ impl Realm {
279330
280331 Ok ( ( ) )
281332 }
282- pub fn get_realm_key ( & self ) -> Result < [ u8 ; 97 ] , Error > {
283- let rak = self . rak ;
333+
334+ pub fn get_realm_key ( & self ) -> Result < Vec < u8 > , Error > {
335+ let rak = if self . profile == REALM_PROFILE {
336+ self . cose_rak . clone ( )
337+ } else {
338+ self . raw_rak . clone ( ) . to_vec ( )
339+ } ;
340+
284341 if rak. is_empty ( ) {
285342 return Err ( Error :: MissingClaim ( "No realm Key" . to_string ( ) ) ) ;
286343 }
344+
287345 Ok ( rak)
288346 }
289347
290348 pub fn get_rak_hash_alg ( & self ) -> Result < String , Error > {
291349 let rak_hash_alg = self . rak_hash_alg . clone ( ) ;
350+
292351 if rak_hash_alg. is_empty ( ) {
293352 return Err ( Error :: MissingClaim ( "No realm hash alg" . to_string ( ) ) ) ;
294353 }
354+
295355 Ok ( rak_hash_alg)
296356 }
297357}
0 commit comments