@@ -61,6 +61,7 @@ type storedKeyIface interface {
6161 kind () string
6262 needRewrite (* storedKeyConfig , * StoredKeysState , * storedKeysCtx ) (bool , int , error )
6363 ad () []byte
64+ asBytes () ([]byte , error )
6465 encryptMe (* StoredKeysState , * storedKeysCtx ) error
6566 decryptMe (bool , * StoredKeysState , * storedKeysCtx ) error
6667 encryptData ([]byte , []byte ) ([]byte , error )
@@ -91,6 +92,7 @@ const (
9192 encryptedFileHeaderSize = 80
9293 encryptedFileKeyNameLength = byte (36 )
9394 macLen = 101 // Vsn: 1B, UUID: 36B, MAC: 64B
95+ intTokenSize = 64
9496)
9597
9698// Struct for marshalling/unmarshalling of a raw aes-gcm stored key
@@ -286,11 +288,14 @@ func (state *StoredKeysState) maybeRegenerateProof(path, name string, ctx *store
286288 logDbg ("Failed to read key %s from file %s: %s" , name , filePathPrefix , err .Error ())
287289 return err
288290 }
289- parts := strings .Split (proof , ":" )
290- if len (parts ) != 2 {
291- return fmt .Errorf ("file %s has invalid proof format" , filePathPrefix )
291+ proofBytes , err := base64 .StdEncoding .DecodeString (proof )
292+ if err != nil {
293+ return fmt .Errorf ("file %s has invalid proof format: %s" , filePathPrefix , err .Error ())
294+ }
295+ uuid , _ , err := parseMac (proofBytes )
296+ if err != nil {
297+ return fmt .Errorf ("file %s has invalid proof format: %s" , filePathPrefix , err .Error ())
292298 }
293- uuid := parts [0 ]
294299 if uuid == state .intTokens [0 ].uuid {
295300 // Proof is still valid, no need to regenerate proof
296301 return nil
@@ -312,7 +317,7 @@ func (state *StoredKeysState) maybeRegenerateProof(path, name string, ctx *store
312317func (state * StoredKeysState ) generateIntToken (ctx * storedKeysCtx ) error {
313318 newToken := intToken {
314319 uuid : uuid .New ().String (),
315- token : createRandomKey ( ),
320+ token : generateRandomBytes ( intTokenSize ),
316321 }
317322 prevTokens := state .intTokens
318323 state .intTokens = append ([]intToken {newToken }, state .intTokens ... )
@@ -415,47 +420,52 @@ func (state *StoredKeysState) mac(data []byte) ([]byte, error) {
415420 return nil , fmt .Errorf ("no keys" )
416421 }
417422 token := state .intTokens [0 ]
418- h := hmac .New (sha512 .New , token .token )
419- h .Write (data )
420- mac := h .Sum (nil )
423+ hmacBytes := hmacSHA512 (token .token , data )
421424 // Format: Version: 1 byte, TokenUUID, MAC
422425 res := append ([]byte {0 }, token .uuid ... )
423- res = append (res , mac ... )
426+ res = append (res , hmacBytes ... )
424427 if len (res ) != macLen {
425428 return nil , fmt .Errorf ("unexpected mac length: %d" , len (res ))
426429 }
427430 return res , nil
428431}
429432
430433func (state * StoredKeysState ) verifyMac (mac , data []byte ) error {
434+ uuid , hmacBytes , err := parseMac (mac )
435+ if err != nil {
436+ return err
437+ }
438+ for _ , token := range state .intTokens {
439+ if token .uuid == uuid {
440+ expectedHmacBytes := hmacSHA512 (token .token , data )
441+ if hmac .Equal (hmacBytes , expectedHmacBytes ) {
442+ return nil
443+ }
444+ return fmt .Errorf ("invalid mac (token uuid: %s)" , uuid )
445+ }
446+ }
447+ return fmt .Errorf ("unknown token: %s" , uuid )
448+ }
449+
450+ // Format: Version = 0: 1 byte, TokenUUID (36 bytes), MAC (64 bytes)
451+ func parseMac (mac []byte ) (string , []byte , error ) {
431452 if len (mac ) == 0 {
432- return fmt .Errorf ("mac is empty" )
453+ return "" , nil , fmt .Errorf ("mac is empty" )
433454 }
434455 if mac [0 ] != 0 {
435- return fmt .Errorf ("unknown mac version: %v" , mac [0 ])
456+ return "" , nil , fmt .Errorf ("unknown mac version: %v" , mac [0 ])
436457 }
437458
438459 if len (mac ) != macLen {
439- return fmt .Errorf ("unexpected mac length: %d" , len (mac ))
460+ return "" , nil , fmt .Errorf ("unexpected mac length: %d" , len (mac ))
440461 }
441462 uuidBytes := mac [1 :37 ]
442463 if ! utf8 .Valid (uuidBytes ) {
443- return fmt .Errorf ("invalid utf-8 in uuid: %q" , uuidBytes )
464+ return "" , nil , fmt .Errorf ("invalid utf-8 in uuid: %q" , uuidBytes )
444465 }
445466 uuid := string (uuidBytes )
446- mac = mac [37 :]
447- for _ , token := range state .intTokens {
448- if token .uuid == uuid {
449- h := hmac .New (sha512 .New , token .token )
450- h .Write (data )
451- expectedMac := h .Sum (nil )
452- if hmac .Equal (mac , expectedMac ) {
453- return nil
454- }
455- return fmt .Errorf ("invalid mac" )
456- }
457- }
458- return fmt .Errorf ("unknown token: %s" , uuid )
467+ hmacBytes := mac [37 :]
468+ return uuid , hmacBytes , nil
459469}
460470
461471func (state * StoredKeysState ) revalidateKeyCache (ctx * storedKeysCtx ) {
@@ -850,9 +860,9 @@ func (state *StoredKeysState) decryptKey(keyIface storedKeyIface, validateProof
850860 return err
851861 }
852862 if validateProof {
853- err = validateKeyProof (keyIface , proof , state . intTokens )
863+ err = state . validateKeyProof (keyIface , proof )
854864 if err != nil {
855- return err
865+ return fmt . Errorf ( "key integrity check failed for key %s: %s" , keyIface . name (), err . Error ())
856866 }
857867 }
858868 if keyIface .canBeCached () {
@@ -872,7 +882,7 @@ func (state *StoredKeysState) writeKeyToFile(keyIface storedKeyIface, curVsn int
872882 if err != nil {
873883 return err
874884 }
875- proof , err := generateKeyProof (keyIface , state . intTokens )
885+ proof , err := state . generateKeyProof (keyIface )
876886 if err != nil {
877887 return err
878888 }
@@ -908,48 +918,40 @@ func (state *StoredKeysState) writeKeyToFile(keyIface storedKeyIface, curVsn int
908918 return nil
909919}
910920
911- func generateKeyProof (keyIface storedKeyIface , intTokens []intToken ) (string , error ) {
912- if len (intTokens ) == 0 {
913- return "" , fmt .Errorf ("failed to generate proof: empty integrity tokens" )
921+ func (state * StoredKeysState ) generateKeyProof (keyIface storedKeyIface ) (string , error ) {
922+ keyBytes , err := keyIface .asBytes ()
923+ if err != nil {
924+ return "" , fmt .Errorf ("failed to convert key to bytes: %s" , err .Error ())
914925 }
915- tokenHash := tokenHash (intTokens [0 ], keyIface )
916- encryptedTokenHash , err := keyIface .encryptData (tokenHash [:], []byte (keyIface .name ()))
926+ proofBytes , err := state .mac (keyBytes )
917927 if err != nil {
918- return "" , fmt . Errorf ( "failed to use key to generate proof: %s" , err . Error ())
928+ return "" , err
919929 }
920- proof := fmt . Sprintf ( "%s:%s" , intTokens [ 0 ]. uuid , base64 .StdEncoding .EncodeToString (encryptedTokenHash ) )
921- return proof , nil
930+ proofStr := base64 .StdEncoding .EncodeToString (proofBytes )
931+ return proofStr , nil
922932}
923933
924- func validateKeyProof (keyIface storedKeyIface , proof string , intTokens [] intToken ) error {
925- parts := strings . Split (proof , ":" )
926- if len ( parts ) != 2 {
927- return fmt .Errorf ("key integrity check failed: invalid proof format" )
934+ func ( state * StoredKeysState ) validateKeyProof (keyIface storedKeyIface , proof string ) error {
935+ proofBytes , err := base64 . StdEncoding . DecodeString (proof )
936+ if err != nil {
937+ return fmt .Errorf ("failed to decode proof: %s" , err . Error () )
928938 }
929- uuid := parts [0 ]
930- encryptedTokenHashBase64 := parts [1 ]
931- for _ , token := range intTokens {
932- if token .uuid == uuid {
933- encryptedTokenHash , err := base64 .StdEncoding .DecodeString (encryptedTokenHashBase64 )
934- if err != nil {
935- return fmt .Errorf ("key integrity check failed: failed to decode encrypted token hash: %s" , err .Error ())
936- }
937- decryptedTokenHash , err := keyIface .decryptData (encryptedTokenHash , []byte (keyIface .name ()))
938- if err != nil {
939- return fmt .Errorf ("key integrity check failed: failed to decrypt proof: %s" , err .Error ())
940- }
941- tokenHash := tokenHash (token , keyIface )
942- if bytes .Equal (tokenHash [:], decryptedTokenHash ) {
943- return nil
944- }
945- return fmt .Errorf ("key integrity check failed: invalid integrity token (token uuid: %s, key name: %s)" , uuid , keyIface .name ())
946- }
939+ keyBytes , err := keyIface .asBytes ()
940+ if err != nil {
941+ return fmt .Errorf ("failed to convert key to bytes: %s" , err .Error ())
947942 }
948- return fmt .Errorf ("key integrity check failed: unknown token: %s (key name: %s)" , uuid , keyIface .name ())
943+ err = state .verifyMac (proofBytes , keyBytes )
944+ if err != nil {
945+ return err
946+ }
947+ return nil
949948}
950949
951- func tokenHash (token intToken , keyIface storedKeyIface ) [64 ]byte {
952- return sha512 .Sum512 (append (token .token , []byte (keyIface .name ())... ))
950+ func hmacSHA512 (key []byte , data []byte ) []byte {
951+ h := hmac .New (sha512 .New , key )
952+ h .Write (data )
953+ mac := h .Sum (nil )
954+ return mac
953955}
954956
955957func (state * StoredKeysState ) encryptWithKey (keyKind , keyName string , data , AD []byte , ctx * storedKeysCtx ) ([]byte , error ) {
@@ -1313,6 +1315,13 @@ func (k *rawAesGcmStoredKey) ad() []byte {
13131315 return []byte (string (rawAESGCMKey ) + k .Name + k .Kind + k .CreationTime + k .EncryptionKeyName + strconv .FormatBool (k .CanBeCached ))
13141316}
13151317
1318+ func (k * rawAesGcmStoredKey ) asBytes () ([]byte , error ) {
1319+ if k .DecryptedKey == nil {
1320+ return nil , fmt .Errorf ("key %s is encrypted" , k .Name )
1321+ }
1322+ return append (k .ad (), k .DecryptedKey ... ), nil
1323+ }
1324+
13161325func (k * rawAesGcmStoredKey ) encryptMe (state * StoredKeysState , ctx * storedKeysCtx ) error {
13171326 if k .EncryptedKey != nil {
13181327 // Seems like it is already encrypted
@@ -1449,6 +1458,20 @@ func (k *awsStoredKey) ad() []byte {
14491458 return []byte ("" )
14501459}
14511460
1461+ func (k * awsStoredKey ) asBytes () ([]byte , error ) {
1462+ return []byte (
1463+ string (awskmKey ) +
1464+ k .Name +
1465+ k .Kind +
1466+ k .KeyArn +
1467+ k .Region +
1468+ k .ConfigFile +
1469+ k .CredsFile +
1470+ k .Profile +
1471+ strconv .FormatBool (k .UseIMDS ) +
1472+ k .CreationTime ), nil
1473+ }
1474+
14521475func (k * awsStoredKey ) encryptMe (state * StoredKeysState , ctx * storedKeysCtx ) error {
14531476 // Nothing to encrypt here, configuration should contain no secrets
14541477 return nil
@@ -1625,6 +1648,13 @@ func (k *kmipStoredKey) ad() []byte {
16251648 k .CreationTime )
16261649}
16271650
1651+ func (k * kmipStoredKey ) asBytes () ([]byte , error ) {
1652+ if k .decryptedPassphrase == nil {
1653+ return nil , fmt .Errorf ("key %s is encrypted" , k .Name )
1654+ }
1655+ return append (k .ad (), k .decryptedPassphrase ... ), nil
1656+ }
1657+
16281658func (k * kmipStoredKey ) encryptMe (state * StoredKeysState , ctx * storedKeysCtx ) error {
16291659 if k .EncryptedPassphrase != nil {
16301660 // Seems like it is already encrypted
0 commit comments