@@ -6,10 +6,13 @@ use hex_literal::hex;
66use iso7816:: Status ;
77use trussed:: {
88 syscall, try_syscall,
9- types:: { KeySerialization , Mechanism } ,
9+ types:: { KeyId , KeySerialization , Mechanism } ,
1010} ;
1111use trussed_auth:: AuthClient ;
1212
13+ const CHACHA_NONCE_SIZE : usize = 12 ;
14+ const CHACHA_TAG_SIZE : usize = 16 ;
15+
1316use crate :: {
1417 card:: { Context , LoadedContext , Options } ,
1518 command:: { GetDataMode , Password , PutDataMode , Tag } ,
@@ -375,8 +378,12 @@ impl GetDataObject {
375378 Self :: KdfDo => get_arbitrary_do ( context, ArbitraryDO :: KdfDo ) ?,
376379 Self :: PrivateUse1 => get_arbitrary_do ( context, ArbitraryDO :: PrivateUse1 ) ?,
377380 Self :: PrivateUse2 => get_arbitrary_do ( context, ArbitraryDO :: PrivateUse2 ) ?,
378- Self :: PrivateUse3 => get_arbitrary_do ( context, ArbitraryDO :: PrivateUse3 ) ?,
379- Self :: PrivateUse4 => get_arbitrary_do ( context, ArbitraryDO :: PrivateUse4 ) ?,
381+ Self :: PrivateUse3 => {
382+ get_arbitrary_user_enc_do ( context. load_state ( ) ?, ArbitraryDO :: PrivateUse3 ) ?
383+ }
384+ Self :: PrivateUse4 => {
385+ get_arbitrary_admin_enc_do ( context. load_state ( ) ?, ArbitraryDO :: PrivateUse4 ) ?
386+ }
380387 Self :: CardHolderCertificate => cardholder_cert ( context) ?,
381388 Self :: SecureMessagingCertificate => return Err ( Status :: SecureMessagingNotSupported ) ,
382389 Self :: CardHolderRelatedData
@@ -811,6 +818,54 @@ fn get_arbitrary_do<const R: usize, T: trussed::Client + AuthClient>(
811818 ctx. reply . expand ( & data)
812819}
813820
821+ fn get_arbitrary_enc_do < const R : usize , T : trussed:: Client + AuthClient > (
822+ mut ctx : LoadedContext < ' _ , R , T > ,
823+ obj : ArbitraryDO ,
824+ key : KeyId ,
825+ ) -> Result < ( ) , Status > {
826+ let data = obj
827+ . load ( ctx. backend . client_mut ( ) , ctx. options . storage )
828+ . map_err ( |_| Status :: UnspecifiedNonpersistentExecutionError ) ?;
829+ if data. is_empty ( ) {
830+ return Ok ( ( ) ) ;
831+ }
832+ let ( data, tag) = data. split_at ( data. len ( ) - CHACHA_TAG_SIZE ) ;
833+ let ( data, nonce) = data. split_at ( data. len ( ) - CHACHA_NONCE_SIZE ) ;
834+ let decrypted = syscall ! ( ctx. backend. client_mut( ) . decrypt(
835+ Mechanism :: Chacha8Poly1305 ,
836+ key,
837+ data,
838+ & [ ] ,
839+ nonce,
840+ tag
841+ ) )
842+ . plaintext
843+ . ok_or ( Status :: UnspecifiedNonpersistentExecutionError ) ?;
844+ ctx. reply . expand ( & decrypted)
845+ }
846+
847+ /// Get an arbitrary DO encrypted with the user key
848+ fn get_arbitrary_user_enc_do < const R : usize , T : trussed:: Client + AuthClient > (
849+ ctx : LoadedContext < ' _ , R , T > ,
850+ obj : ArbitraryDO ,
851+ ) -> Result < ( ) , Status > {
852+ let Some ( k) = ctx. state . volatile . other_verified_kek ( ) else {
853+ return Err ( Status :: SecurityStatusNotSatisfied ) ;
854+ } ;
855+ get_arbitrary_enc_do ( ctx, obj, k)
856+ }
857+
858+ /// Get an arbitrary DO encrypted with the admin key
859+ fn get_arbitrary_admin_enc_do < const R : usize , T : trussed:: Client + AuthClient > (
860+ ctx : LoadedContext < ' _ , R , T > ,
861+ obj : ArbitraryDO ,
862+ ) -> Result < ( ) , Status > {
863+ let Some ( k) = ctx. state . volatile . admin_kek ( ) else {
864+ return Err ( Status :: SecurityStatusNotSatisfied ) ;
865+ } ;
866+ get_arbitrary_enc_do ( ctx, obj, k)
867+ }
868+
814869// § 7.2.8
815870pub fn put_data < const R : usize , T : trussed:: Client + AuthClient > (
816871 mut context : Context < ' _ , R , T > ,
@@ -889,7 +944,7 @@ enum_subset! {
889944impl PutDataObject {
890945 fn write_perm ( & self ) -> PermissionRequirement {
891946 match self {
892- Self :: PrivateUse2 | Self :: PrivateUse4 => PermissionRequirement :: User ,
947+ Self :: PrivateUse1 | Self :: PrivateUse3 => PermissionRequirement :: User ,
893948 _ => PermissionRequirement :: Admin ,
894949 }
895950 }
@@ -901,8 +956,12 @@ impl PutDataObject {
901956 match self {
902957 Self :: PrivateUse1 => put_arbitrary_do ( ctx, ArbitraryDO :: PrivateUse1 ) ?,
903958 Self :: PrivateUse2 => put_arbitrary_do ( ctx, ArbitraryDO :: PrivateUse2 ) ?,
904- Self :: PrivateUse3 => put_arbitrary_do ( ctx, ArbitraryDO :: PrivateUse3 ) ?,
905- Self :: PrivateUse4 => put_arbitrary_do ( ctx, ArbitraryDO :: PrivateUse4 ) ?,
959+ Self :: PrivateUse3 => {
960+ put_arbitrary_user_enc_do ( ctx. load_state ( ) ?, ArbitraryDO :: PrivateUse3 ) ?
961+ }
962+ Self :: PrivateUse4 => {
963+ put_arbitrary_admin_enc_do ( ctx. load_state ( ) ?, ArbitraryDO :: PrivateUse4 ) ?
964+ }
906965 Self :: LoginData => put_arbitrary_do ( ctx, ArbitraryDO :: LoginData ) ?,
907966 Self :: ExtendedHeaderList => {
908967 super :: private_key_template:: put_private_key_template ( ctx. load_state ( ) ?) ?
@@ -954,7 +1013,7 @@ fn put_cardholder_cert<const R: usize, T: trussed::Client + AuthClient>(
9541013const AES256_KEY_LEN : usize = 32 ;
9551014
9561015fn put_enc_dec_key < const R : usize , T : trussed:: Client + AuthClient > (
957- ctx : LoadedContext < ' _ , R , T > ,
1016+ mut ctx : LoadedContext < ' _ , R , T > ,
9581017) -> Result < ( ) , Status > {
9591018 if ctx. data . len ( ) != AES256_KEY_LEN {
9601019 warn ! (
@@ -976,23 +1035,18 @@ fn put_enc_dec_key<const R: usize, T: trussed::Client + AuthClient>(
9761035 } ) ?
9771036 . key ;
9781037
979- let old_key = ctx
980- . state
981- . persistent
982- . set_aes_key_id ( Some ( new_key) , ctx. backend . client_mut ( ) , ctx. options . storage )
1038+ ctx. state
1039+ . set_aes_key ( new_key, ctx. backend . client_mut ( ) , ctx. options . storage )
9831040 . map_err ( |_err| {
9841041 error ! ( "Failed to set new key: {_err:?}" ) ;
9851042 Status :: UnspecifiedNonpersistentExecutionError
9861043 } ) ?;
987- if let Some ( old_key) = old_key {
988- syscall ! ( ctx. backend. client_mut( ) . delete( old_key) ) ;
989- }
9901044
9911045 Ok ( ( ) )
9921046}
9931047
9941048fn put_resetting_code < const R : usize , T : trussed:: Client + AuthClient > (
995- ctx : LoadedContext < ' _ , R , T > ,
1049+ mut ctx : LoadedContext < ' _ , R , T > ,
9961050) -> Result < ( ) , Status > {
9971051 if ctx. data . is_empty ( ) {
9981052 info ! ( "Removing resetting code" ) ;
@@ -1014,13 +1068,7 @@ fn put_resetting_code<const R: usize, T: trussed::Client + AuthClient>(
10141068 }
10151069
10161070 ctx. state
1017- . persistent
1018- . set_pin (
1019- ctx. backend . client_mut ( ) ,
1020- ctx. options . storage ,
1021- ctx. data ,
1022- Password :: ResetCode ,
1023- )
1071+ . set_reset_code ( ctx. backend . client_mut ( ) , ctx. options . storage , ctx. data )
10241072 . map_err ( |_err| {
10251073 error ! ( "Failed to change resetting code: {_err}" ) ;
10261074 Status :: UnspecifiedNonpersistentExecutionError
@@ -1200,6 +1248,56 @@ fn put_alg_attributes_aut<const R: usize, T: trussed::Client + AuthClient>(
12001248 . map_err ( |_| Status :: UnspecifiedNonpersistentExecutionError )
12011249}
12021250
1251+ fn put_arbitrary_admin_enc_do < const R : usize , T : trussed:: Client + AuthClient > (
1252+ ctx : LoadedContext < ' _ , R , T > ,
1253+ obj : ArbitraryDO ,
1254+ ) -> Result < ( ) , Status > {
1255+ let Some ( k) = ctx. state . volatile . admin_kek ( ) else {
1256+ return Err ( Status :: SecurityStatusNotSatisfied ) ;
1257+ } ;
1258+ put_arbitrary_enc_do ( ctx, obj, k)
1259+ }
1260+ fn put_arbitrary_user_enc_do < const R : usize , T : trussed:: Client + AuthClient > (
1261+ ctx : LoadedContext < ' _ , R , T > ,
1262+ obj : ArbitraryDO ,
1263+ ) -> Result < ( ) , Status > {
1264+ let Some ( k) =ctx. state . volatile . other_verified_kek ( ) else {
1265+ return Err ( Status :: SecurityStatusNotSatisfied ) ;
1266+ } ;
1267+ put_arbitrary_enc_do ( ctx, obj, k)
1268+ }
1269+
1270+ fn put_arbitrary_enc_do < const R : usize , T : trussed:: Client + AuthClient > (
1271+ ctx : LoadedContext < ' _ , R , T > ,
1272+ obj : ArbitraryDO ,
1273+ key : KeyId ,
1274+ ) -> Result < ( ) , Status > {
1275+ if ctx. data . len ( ) + CHACHA_NONCE_SIZE + CHACHA_TAG_SIZE > MAX_GENERIC_LENGTH {
1276+ return Err ( Status :: WrongLength ) ;
1277+ }
1278+ let mut encrypted = syscall ! ( ctx. backend. client_mut( ) . encrypt(
1279+ Mechanism :: Chacha8Poly1305 ,
1280+ key,
1281+ ctx. data,
1282+ & [ ] ,
1283+ None
1284+ ) ) ;
1285+ encrypted
1286+ . ciphertext
1287+ . extend_from_slice ( & encrypted. nonce )
1288+ . map_err ( |_| Status :: NotEnoughMemory ) ?;
1289+ encrypted
1290+ . ciphertext
1291+ . extend_from_slice ( & encrypted. tag )
1292+ . map_err ( |_| Status :: NotEnoughMemory ) ?;
1293+ obj. save (
1294+ ctx. backend . client_mut ( ) ,
1295+ ctx. options . storage ,
1296+ & encrypted. ciphertext ,
1297+ )
1298+ . map_err ( |_| Status :: UnspecifiedPersistentExecutionError )
1299+ }
1300+
12031301fn put_arbitrary_do < const R : usize , T : trussed:: Client + AuthClient > (
12041302 ctx : Context < ' _ , R , T > ,
12051303 obj : ArbitraryDO ,
0 commit comments