1
1
use std:: string:: { String , ToString } ;
2
2
use std:: time:: { SystemTime , UNIX_EPOCH } ;
3
+ use std:: vec;
3
4
4
5
use sgx_tstd:: untrusted:: time:: SystemTimeEx ;
5
6
6
7
use crate :: uuid_to_string;
7
- use jsonwebtoken:: { encode, EncodingKey , Header } ;
8
+ use jsonwebtoken:: { encode, Algorithm , DecodingKey , EncodingKey , Header , TokenData , Validation } ;
8
9
use serde:: { Deserialize , Serialize } ;
10
+ use thiserror:: Error ;
9
11
use uuid:: Uuid ;
10
12
13
+ const HEADER_TYP : & ' static str = "ntlexec+jwt" ;
14
+ const CLAIMS_ISS : & ' static str = "ntls_auth_enclave" ;
15
+ const CLAIMS_AUD : & ' static str = "ntls_exec_enclave" ;
16
+
11
17
/// Claims body of the JWT token
12
18
///
13
19
/// Example output:
14
20
/// ```
15
21
/// {
16
- /// "iss": "registree_auth_enclave ",
22
+ /// "iss": "ntls_auth_enclave ",
17
23
/// "nbf": 1623762799,
18
24
/// "iat": 1623762799,
19
25
/// "jti": "b300fe149d144e05aa9a9600816b42ca",
@@ -22,15 +28,15 @@ use uuid::Uuid;
22
28
/// }
23
29
/// ```
24
30
#[ derive( Debug , Serialize , Deserialize ) ]
25
- struct Claims {
31
+ pub ( crate ) struct Claims {
26
32
// TODO: serialize to hex string? This can be mrenclave or mrsigner
27
33
iss : String ,
28
34
nbf : u64 ,
29
35
iat : u64 ,
30
- jti : String ,
36
+ pub ( crate ) jti : String ,
31
37
// TODO: Better names. use `x-ntls-mod-hash` etc?
32
- exec_module_hash : String ,
33
- dataset_uuid : String ,
38
+ pub ( crate ) exec_module_hash : String ,
39
+ pub ( crate ) dataset_uuid : String , // TODO: use sub?
34
40
}
35
41
36
42
impl Claims {
@@ -42,7 +48,7 @@ impl Claims {
42
48
. as_secs ( ) ;
43
49
44
50
Self {
45
- iss : "registree_auth_enclave" . to_string ( ) ,
51
+ iss : CLAIMS_ISS . to_string ( ) ,
46
52
nbf : now,
47
53
iat : now,
48
54
jti : token_id,
@@ -52,6 +58,43 @@ impl Claims {
52
58
}
53
59
}
54
60
61
+ #[ derive( Debug , Error ) ]
62
+ pub ( crate ) enum DecodeError {
63
+ #[ error( "Decoding failed: {}" , . 0 ) ]
64
+ JWT ( #[ from] jsonwebtoken:: errors:: Error ) ,
65
+ #[ error( "Invalid typ field in the jwt header" ) ]
66
+ Typ ,
67
+ }
68
+
69
+ pub ( crate ) struct DecodedExecutionToken ( TokenData < Claims > ) ;
70
+
71
+ impl DecodedExecutionToken {
72
+ pub ( crate ) fn decode ( token : & str ) -> Result < DecodedExecutionToken , DecodeError > {
73
+ let validation = Validation {
74
+ validate_nbf : true ,
75
+ iss : Some ( CLAIMS_ISS . to_string ( ) ) ,
76
+ algorithms : vec ! [ Algorithm :: HS256 ] ,
77
+
78
+ ..Validation :: default ( )
79
+ } ;
80
+
81
+ let decoded = jsonwebtoken:: decode :: < Claims > ( token, & get_decoding_key ( ) , & validation) ?;
82
+
83
+ match decoded. header . typ . as_deref ( ) {
84
+ Some ( HEADER_TYP ) => Ok ( DecodedExecutionToken ( decoded) ) ,
85
+ Some ( _) | None => Err ( DecodeError :: Typ ) ,
86
+ }
87
+ }
88
+
89
+ pub ( crate ) fn claims < ' a > ( & ' a self ) -> & ' a Claims {
90
+ & self . 0 . claims
91
+ }
92
+
93
+ pub ( crate ) fn header < ' a > ( & ' a self ) -> & ' a Header {
94
+ & self . 0 . header
95
+ }
96
+ }
97
+
55
98
pub ( crate ) struct EncodedExecutionToken {
56
99
pub token : String ,
57
100
pub token_id : Uuid ,
@@ -67,14 +110,12 @@ impl EncodedExecutionToken {
67
110
uuid_to_string ( token_id) ,
68
111
) ;
69
112
70
- // TODO: Use a signing key that corresponds to the public key
71
- // in the attestation enclave held data and move to crypto module in tenclave.
72
- let encoding_key = EncodingKey :: from_secret ( "secret" . as_ref ( ) ) ;
113
+ let encoding_key = get_encoding_key ( ) ;
73
114
// Header size 48 characters base64
74
115
let header = Header {
75
116
// Explicit typing for the token type
76
117
// SEE: https://datatracker.ietf.org/doc/html/draft-ietf-secevent-token-02#section-2.2
77
- typ : Some ( "ntlexec+jwt" . to_string ( ) ) ,
118
+ typ : Some ( HEADER_TYP . to_string ( ) ) ,
78
119
..Header :: default ( )
79
120
} ;
80
121
@@ -85,3 +126,14 @@ impl EncodedExecutionToken {
85
126
Self { token, token_id }
86
127
}
87
128
}
129
+
130
+ fn get_encoding_key ( ) -> EncodingKey {
131
+ // TODO: Use a signing key that corresponds to the public key
132
+ // in the attestation enclave held data and move to crypto module in tenclave.
133
+ EncodingKey :: from_secret ( "secret" . as_ref ( ) )
134
+ }
135
+
136
+ fn get_decoding_key < ' a > ( ) -> DecodingKey < ' a > {
137
+ // TODO: Use a decoding key that can is intrinsic to this enclave instance.
138
+ DecodingKey :: from_secret ( "secret" . as_ref ( ) )
139
+ }
0 commit comments