Mostly Revert 52426 - Drop AVCP support for 3DES

Support is still needed for ACVP until 2023

Change-Id: Ia131a85bc06e7c61c823f1b3c021e2625a8769c4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/53465
Reviewed-by: Corie Pressley <cpressley@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
chromium-5359
Bob Beck 3 years ago committed by Boringssl LUCI CQ
parent 1ced57a1bc
commit b95124305a
  1. 128
      util/fipstools/acvp/acvptool/subprocess/block.go
  2. 2
      util/fipstools/acvp/acvptool/subprocess/subprocess.go
  3. BIN
      util/fipstools/acvp/acvptool/test/expected/ACVP-TDES-CBC.bz2
  4. BIN
      util/fipstools/acvp/acvptool/test/expected/ACVP-TDES-ECB.bz2
  5. 2
      util/fipstools/acvp/acvptool/test/tests.json
  6. BIN
      util/fipstools/acvp/acvptool/test/vectors/ACVP-TDES-CBC.bz2
  7. BIN
      util/fipstools/acvp/acvptool/test/vectors/ACVP-TDES-ECB.bz2

@ -18,6 +18,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/bits"
) )
// aesKeyShuffle is the "AES Monte Carlo Key Shuffle" from the ACVP // aesKeyShuffle is the "AES Monte Carlo Key Shuffle" from the ACVP
@ -118,6 +119,113 @@ func iterateAESCBC(transact func(n int, args ...[]byte) ([][]byte, error), encry
return mctResults return mctResults
} }
// xorKeyWithOddParityLSB XORs value into key while setting the LSB of each bit
// to establish odd parity. This embedding of a parity check in a DES key is an
// old tradition and something that NIST's tests require (despite being
// undocumented).
func xorKeyWithOddParityLSB(key, value []byte) {
for i := range key {
v := key[i] ^ value[i]
// Use LSB to establish odd parity.
v ^= byte((bits.OnesCount8(v) & 1)) ^ 1
key[i] = v
}
}
// desKeyShuffle implements the manipulation of the Key arrays in the "TDES
// Monte Carlo Test - ECB mode" algorithm from the ACVP specification.
func keyShuffle3DES(key, result, prevResult, prevPrevResult []byte) {
xorKeyWithOddParityLSB(key[:8], result)
xorKeyWithOddParityLSB(key[8:16], prevResult)
xorKeyWithOddParityLSB(key[16:], prevPrevResult)
}
// iterate3DES implements "TDES Monte Carlo Test - ECB mode" from the ACVP
// specification.
func iterate3DES(transact func(n int, args ...[]byte) ([][]byte, error), encrypt bool, key, input, iv []byte) (mctResults []blockCipherMCTResult) {
for i := 0; i < 400; i++ {
var iteration blockCipherMCTResult
keyHex := hex.EncodeToString(key)
iteration.Key1Hex = keyHex[:16]
iteration.Key2Hex = keyHex[16:32]
iteration.Key3Hex = keyHex[32:]
if encrypt {
iteration.PlaintextHex = hex.EncodeToString(input)
} else {
iteration.CiphertextHex = hex.EncodeToString(input)
}
results, err := transact(3, key, input, uint32le(10000))
if err != nil {
panic("block operation failed")
}
result := results[0]
prevResult := results[1]
prevPrevResult := results[2]
if encrypt {
iteration.CiphertextHex = hex.EncodeToString(result)
} else {
iteration.PlaintextHex = hex.EncodeToString(result)
}
keyShuffle3DES(key, result, prevResult, prevPrevResult)
mctResults = append(mctResults, iteration)
input = result
}
return mctResults
}
// iterate3DESCBC implements "TDES Monte Carlo Test - CBC mode" from the ACVP
// specification.
func iterate3DESCBC(transact func(n int, args ...[]byte) ([][]byte, error), encrypt bool, key, input, iv []byte) (mctResults []blockCipherMCTResult) {
for i := 0; i < 400; i++ {
var iteration blockCipherMCTResult
keyHex := hex.EncodeToString(key)
iteration.Key1Hex = keyHex[:16]
iteration.Key2Hex = keyHex[16:32]
iteration.Key3Hex = keyHex[32:]
if encrypt {
iteration.PlaintextHex = hex.EncodeToString(input)
} else {
iteration.CiphertextHex = hex.EncodeToString(input)
}
iteration.IVHex = hex.EncodeToString(iv)
results, err := transact(3, key, input, iv, uint32le(10000))
if err != nil {
panic("block operation failed")
}
result := results[0]
prevResult := results[1]
prevPrevResult := results[2]
if encrypt {
iteration.CiphertextHex = hex.EncodeToString(result)
} else {
iteration.PlaintextHex = hex.EncodeToString(result)
}
keyShuffle3DES(key, result, prevResult, prevPrevResult)
if encrypt {
input = prevResult
iv = result
} else {
iv = prevResult
input = result
}
mctResults = append(mctResults, iteration)
}
return mctResults
}
// blockCipher implements an ACVP algorithm by making requests to the subprocess // blockCipher implements an ACVP algorithm by making requests to the subprocess
// to encrypt and decrypt with a block cipher. // to encrypt and decrypt with a block cipher.
type blockCipher struct { type blockCipher struct {
@ -148,6 +256,11 @@ type blockCipherTestGroup struct {
CiphertextHex string `json:"ct"` CiphertextHex string `json:"ct"`
IVHex string `json:"iv"` IVHex string `json:"iv"`
KeyHex string `json:"key"` KeyHex string `json:"key"`
// 3DES tests serialise the key differently.
Key1Hex string `json:"key1"`
Key2Hex string `json:"key2"`
Key3Hex string `json:"key3"`
} `json:"tests"` } `json:"tests"`
} }
@ -168,6 +281,11 @@ type blockCipherMCTResult struct {
PlaintextHex string `json:"pt"` PlaintextHex string `json:"pt"`
CiphertextHex string `json:"ct"` CiphertextHex string `json:"ct"`
IVHex string `json:"iv,omitempty"` IVHex string `json:"iv,omitempty"`
// 3DES tests serialise the key differently.
Key1Hex string `json:"key1,omitempty"`
Key2Hex string `json:"key2,omitempty"`
Key3Hex string `json:"key3,omitempty"`
} }
func (b *blockCipher) Process(vectorSet []byte, m Transactable) (interface{}, error) { func (b *blockCipher) Process(vectorSet []byte, m Transactable) (interface{}, error) {
@ -213,6 +331,11 @@ func (b *blockCipher) Process(vectorSet []byte, m Transactable) (interface{}, er
return nil, fmt.Errorf("test group %d has unknown type %q", group.ID, group.Type) return nil, fmt.Errorf("test group %d has unknown type %q", group.ID, group.Type)
} }
if group.KeyBits == 0 {
// 3DES tests fail to set this parameter.
group.KeyBits = 192
}
if group.KeyBits%8 != 0 { if group.KeyBits%8 != 0 {
return nil, fmt.Errorf("test group %d contains non-byte-multiple key length %d", group.ID, group.KeyBits) return nil, fmt.Errorf("test group %d contains non-byte-multiple key length %d", group.ID, group.KeyBits)
} }
@ -223,6 +346,11 @@ func (b *blockCipher) Process(vectorSet []byte, m Transactable) (interface{}, er
} }
for _, test := range group.Tests { for _, test := range group.Tests {
if len(test.KeyHex) == 0 && len(test.Key1Hex) > 0 {
// 3DES encodes the key differently.
test.KeyHex = test.Key1Hex + test.Key2Hex + test.Key3Hex
}
if len(test.KeyHex) != keyBytes*2 { if len(test.KeyHex) != keyBytes*2 {
return nil, fmt.Errorf("test case %d/%d contains key %q of length %d, but expected %d-bit key", group.ID, test.ID, test.KeyHex, len(test.KeyHex), group.KeyBits) return nil, fmt.Errorf("test case %d/%d contains key %q of length %d, but expected %d-bit key", group.ID, test.ID, test.KeyHex, len(test.KeyHex), group.KeyBits)
} }

@ -85,6 +85,8 @@ func NewWithIO(cmd *exec.Cmd, in io.WriteCloser, out io.ReadCloser) *Subprocess
"ACVP-AES-CBC": &blockCipher{"AES-CBC", 16, 2, true, true, iterateAESCBC}, "ACVP-AES-CBC": &blockCipher{"AES-CBC", 16, 2, true, true, iterateAESCBC},
"ACVP-AES-CBC-CS3": &blockCipher{"AES-CBC-CS3", 16, 1, false, true, iterateAESCBC}, "ACVP-AES-CBC-CS3": &blockCipher{"AES-CBC-CS3", 16, 1, false, true, iterateAESCBC},
"ACVP-AES-CTR": &blockCipher{"AES-CTR", 16, 1, false, true, nil}, "ACVP-AES-CTR": &blockCipher{"AES-CTR", 16, 1, false, true, nil},
"ACVP-TDES-ECB": &blockCipher{"3DES-ECB", 8, 3, true, false, iterate3DES},
"ACVP-TDES-CBC": &blockCipher{"3DES-CBC", 8, 3, true, true, iterate3DESCBC},
"ACVP-AES-XTS": &xts{}, "ACVP-AES-XTS": &xts{},
"ACVP-AES-GCM": &aead{"AES-GCM", false}, "ACVP-AES-GCM": &aead{"AES-GCM", false},
"ACVP-AES-GMAC": &aead{"AES-GCM", false}, "ACVP-AES-GMAC": &aead{"AES-GCM", false},

@ -9,6 +9,8 @@
{"Wrapper": "modulewrapper", "In": "vectors/ACVP-AES-KW.bz2", "Out": "expected/ACVP-AES-KW.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/ACVP-AES-KW.bz2", "Out": "expected/ACVP-AES-KW.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ACVP-AES-KWP.bz2", "Out": "expected/ACVP-AES-KWP.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/ACVP-AES-KWP.bz2", "Out": "expected/ACVP-AES-KWP.bz2"},
{"Wrapper": "testmodulewrapper", "In": "vectors/ACVP-AES-XTS.bz2", "Out": "expected/ACVP-AES-XTS.bz2"}, {"Wrapper": "testmodulewrapper", "In": "vectors/ACVP-AES-XTS.bz2", "Out": "expected/ACVP-AES-XTS.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ACVP-TDES-CBC.bz2", "Out": "expected/ACVP-TDES-CBC.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ACVP-TDES-ECB.bz2", "Out": "expected/ACVP-TDES-ECB.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/CMAC-AES.bz2", "Out": "expected/CMAC-AES.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/CMAC-AES.bz2", "Out": "expected/CMAC-AES.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ctrDRBG.bz2", "Out": "expected/ctrDRBG.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/ctrDRBG.bz2", "Out": "expected/ctrDRBG.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ECDSA.bz2", "Out": "expected/ECDSA.bz2"}, {"Wrapper": "modulewrapper", "In": "vectors/ECDSA.bz2", "Out": "expected/ECDSA.bz2"},

Loading…
Cancel
Save