@@ -3,7 +3,9 @@ use crate::{PublicKey, TouchRequirement};
33use ring:: digest;
44
55use yubikey:: certificate:: Certificate ;
6- use yubikey:: piv:: { attest, sign_data as yk_sign_data, AlgorithmId , SlotId } ;
6+ use yubikey:: piv:: {
7+ attest, sign_data as yk_sign_data, AlgorithmId , ManagementSlotId , SlotAlgorithmId , SlotId ,
8+ } ;
79use yubikey:: { MgmAlgorithmId , MgmKey , Serial , YubiKey } ;
810use yubikey:: { PinPolicy , TouchPolicy } ;
911
@@ -209,11 +211,28 @@ impl super::Yubikey {
209211 Ok ( ( ) )
210212 }
211213
212- fn management_key_from_bytes ( & self , mgm_key : & [ u8 ] ) -> Result < MgmKey > {
213- let alg = MgmKey :: get_default ( & self . yk ) ?. algorithm_id ( ) ;
214+ fn management_key_from_bytes ( & mut self , mgm_key : & [ u8 ] ) -> Result < MgmKey > {
215+ // Use the configured algorithm when metadata is available. Older
216+ // devices fall back to their default algorithm.
217+ let alg = match self . management_key_algorithm ( ) ? {
218+ Some ( alg) => alg,
219+ None => MgmKey :: get_default ( & self . yk ) ?. algorithm_id ( ) ,
220+ } ;
214221 MgmKey :: from_bytes ( mgm_key, Some ( alg) ) . map_err ( |_| Error :: InvalidManagementKey )
215222 }
216223
224+ /// The algorithm the management key is currently set to, if the device
225+ /// exposes it via metadata.
226+ fn management_key_algorithm ( & mut self ) -> Result < Option < MgmAlgorithmId > > {
227+ let slot = SlotId :: Management ( ManagementSlotId :: Management ) ;
228+ match yubikey:: piv:: metadata ( & mut self . yk , slot) . map ( |m| m. algorithm ) {
229+ Ok ( SlotAlgorithmId :: Management ( alg) ) => Ok ( Some ( alg) ) ,
230+ Ok ( _) => Ok ( None ) ,
231+ Err ( yubikey:: Error :: NotSupported ) => Ok ( None ) ,
232+ Err ( e) => Err ( e. into ( ) ) ,
233+ }
234+ }
235+
217236 /// Fetch the serial number of the Yubikey
218237 pub fn serial ( & mut self ) -> Result < Serial > {
219238 let serial = self . yk . serial ( ) ;
0 commit comments