| // Copyright 2019 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package wycheproof |
| |
| import ( |
| "crypto/aes" |
| "crypto/cipher" |
| "encoding/hex" |
| "fmt" |
| "testing" |
| ) |
| |
| func TestAesCbc(t *testing.T) { |
| // IndCpaTestVector |
| type IndCpaTestVector struct { |
| |
| // A brief description of the test case |
| Comment string `json:"comment,omitempty"` |
| |
| // the raw ciphertext (without IV) |
| Ct string `json:"ct,omitempty"` |
| |
| // A list of flags |
| Flags []string `json:"flags,omitempty"` |
| |
| // the initialization vector |
| Iv string `json:"iv,omitempty"` |
| |
| // the key |
| Key string `json:"key,omitempty"` |
| |
| // the plaintext |
| Msg string `json:"msg,omitempty"` |
| |
| // Test result |
| Result string `json:"result,omitempty"` |
| |
| // Identifier of the test case |
| TcId int `json:"tcId,omitempty"` |
| } |
| |
| // Notes a description of the labels used in the test vectors |
| type Notes struct { |
| } |
| |
| // IndCpaTestGroup |
| type IndCpaTestGroup struct { |
| |
| // the IV size in bits |
| IvSize int `json:"ivSize,omitempty"` |
| |
| // the keySize in bits |
| KeySize int `json:"keySize,omitempty"` |
| |
| // the expected size of the tag in bits |
| TagSize int `json:"tagSize,omitempty"` |
| Tests []*IndCpaTestVector `json:"tests,omitempty"` |
| Type interface{} `json:"type,omitempty"` |
| } |
| |
| // Root |
| type Root struct { |
| |
| // the primitive tested in the test file |
| Algorithm string `json:"algorithm,omitempty"` |
| |
| // the version of the test vectors. |
| GeneratorVersion string `json:"generatorVersion,omitempty"` |
| |
| // additional documentation |
| Header []string `json:"header,omitempty"` |
| |
| // a description of the labels used in the test vectors |
| Notes *Notes `json:"notes,omitempty"` |
| |
| // the number of test vectors in this test |
| NumberOfTests int `json:"numberOfTests,omitempty"` |
| Schema interface{} `json:"schema,omitempty"` |
| TestGroups []*IndCpaTestGroup `json:"testGroups,omitempty"` |
| } |
| |
| var root Root |
| readTestVector(t, "aes_cbc_pkcs5_test.json", &root) |
| for _, tg := range root.TestGroups { |
| tests: |
| for _, tv := range tg.Tests { |
| block, err := aes.NewCipher(decodeHex(tv.Key)) |
| if err != nil { |
| t.Fatalf("#%d: %v", tv.TcId, err) |
| } |
| mode := cipher.NewCBCDecrypter(block, decodeHex(tv.Iv)) |
| ct := decodeHex(tv.Ct) |
| if len(ct)%aes.BlockSize != 0 { |
| panic(fmt.Sprintf("#%d: ciphertext is not a multiple of the block size", tv.TcId)) |
| } |
| mode.CryptBlocks(ct, ct) // decrypt the block in place |
| |
| // Skip the tests that are broken due to bad padding. Panic if there are any |
| // tests left that are invalid for some other reason in the future, to |
| // evaluate what to do with those tests. |
| for _, flag := range tv.Flags { |
| if flag == "BadPadding" { |
| continue tests |
| } |
| } |
| if !shouldPass(tv.Result, tv.Flags, nil) { |
| panic(fmt.Sprintf("#%d: found an invalid test that is broken for some reason other than bad padding", tv.TcId)) |
| } |
| |
| // Remove the PKCS#5 padding from the given ciphertext to validate it |
| padding := ct[len(ct)-1] |
| paddingNum := int(padding) |
| for i := paddingNum; i > 0; i-- { |
| if ct[len(ct)-i] != padding { // panic if the padding is unexpectedly bad |
| panic(fmt.Sprintf("#%d: bad padding at index=%d of %v", tv.TcId, i, ct)) |
| } |
| } |
| ct = ct[:len(ct)-paddingNum] |
| |
| if got, want := hex.EncodeToString(ct), tv.Msg; got != want { |
| t.Errorf("#%d, type: %s, comment: %q, decoded ciphertext not equal: %s, want %s", tv.TcId, tv.Result, tv.Comment, got, want) |
| } |
| } |
| } |
| } |