diff --git a/globalplatform/crypto/crypto.go b/globalplatform/crypto/crypto.go index 1b64de6..98c1288 100644 --- a/globalplatform/crypto/crypto.go +++ b/globalplatform/crypto/crypto.go @@ -44,6 +44,37 @@ func VerifyCryptogram(encKey, hostChallenge, cardChallenge, cardCryptogram []byt return bytes.Equal(calculated, cardCryptogram), nil } +func MacFull3DES(key, data, iv []byte) ([]byte, error) { + data = appendDESPadding(data) + + desBlock, err := des.NewCipher(resizeKey8(key)) + if err != nil { + return nil, err + } + + des3Block, err := des.NewTripleDESCipher(resizeKey24(key)) + if err != nil { + return nil, err + } + + des3IV := iv + + if len(data) > 8 { + length := len(data) - 8 + tmp := make([]byte, length) + mode := cipher.NewCBCEncrypter(desBlock, iv) + mode.CryptBlocks(tmp, data[:length]) + des3IV = tmp + } + + ciphertext := make([]byte, 8) + + mode := cipher.NewCBCEncrypter(des3Block, des3IV) + mode.CryptBlocks(ciphertext, data[len(data)-8:]) + + return ciphertext, nil +} + func mac3des(key, data, iv []byte) ([]byte, error) { key24 := resizeKey24(key) @@ -68,6 +99,10 @@ func resizeKey24(key []byte) []byte { return data } +func resizeKey8(key []byte) []byte { + return key[:8] +} + func appendDESPadding(data []byte) []byte { length := len(data) + 1 for ; length%8 != 0; length++ { diff --git a/globalplatform/crypto/crypto_test.go b/globalplatform/crypto/crypto_test.go index 8779beb..dc4c884 100644 --- a/globalplatform/crypto/crypto_test.go +++ b/globalplatform/crypto/crypto_test.go @@ -52,3 +52,12 @@ func TestMac3des(t *testing.T) { expected := "05C4BB8A86014E22" assert.Equal(t, expected, hexutils.BytesToHex(result)) } + +func TestMacFull3DES(t *testing.T) { + key := hexutils.HexToBytes("5b02e75ad63190aece0622936f11abab") + data := hexutils.HexToBytes("8482010010810b098a8fbb88da") + result, err := MacFull3DES(key, data, nullBytes8) + assert.NoError(t, err) + expected := "5271D7174A5A166A" + assert.Equal(t, expected, hexutils.BytesToHex(result)) +}