github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/bsaes/aes_test.go (about)

     1  // aes_test.go - AES tests.
     2  //
     3  // To the extent possible under law, Yawning Angel has waived all copyright
     4  // and related or neighboring rights to aes_test.go, using the Creative
     5  // Commons "CC0" public domain dedication. See LICENSE or
     6  // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
     7  
     8  package bsaes
     9  
    10  import (
    11  	"bytes"
    12  	"crypto/aes"
    13  	"crypto/cipher"
    14  	"crypto/rand"
    15  	"encoding/hex"
    16  	"fmt"
    17  	"math"
    18  	"testing"
    19  
    20  	"git.schwanenlied.me/yawning/bsaes.git/ct32"
    21  	"git.schwanenlied.me/yawning/bsaes.git/ct64"
    22  )
    23  
    24  type Impl struct {
    25  	name string
    26  	ctor func([]byte) cipher.Block
    27  }
    28  
    29  var (
    30  	implCt32    = &Impl{"ct32", ct32.NewCipher}
    31  	implCt64    = &Impl{"ct64", ct64.NewCipher}
    32  	implRuntime = &Impl{"runtime", func(k []byte) cipher.Block {
    33  		blk, err := NewCipher(k)
    34  		if err != nil {
    35  			panic("implRuntime: NewCipher failed: " + err.Error())
    36  		}
    37  		return blk
    38  	}}
    39  
    40  	impls      = []*Impl{implCt32, implCt64}
    41  	nativeImpl = implCt64
    42  )
    43  
    44  // The test vectors are shamelessly stolen from NIST Special Pub. 800-38A,
    45  // my tax dollars at work.
    46  //
    47  // http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
    48  
    49  var ecbVectors = []struct {
    50  	key        string
    51  	plaintext  string
    52  	ciphertext string
    53  }{
    54  	// ECB-AES128
    55  	{
    56  		"2b7e151628aed2a6abf7158809cf4f3c",
    57  		"6bc1bee22e409f96e93d7e117393172a",
    58  		"3ad77bb40d7a3660a89ecaf32466ef97",
    59  	},
    60  	{
    61  		"2b7e151628aed2a6abf7158809cf4f3c",
    62  		"ae2d8a571e03ac9c9eb76fac45af8e51",
    63  		"f5d3d58503b9699de785895a96fdbaaf",
    64  	},
    65  	{
    66  		"2b7e151628aed2a6abf7158809cf4f3c",
    67  		"30c81c46a35ce411e5fbc1191a0a52ef",
    68  		"43b1cd7f598ece23881b00e3ed030688",
    69  	},
    70  	{
    71  		"2b7e151628aed2a6abf7158809cf4f3c",
    72  		"f69f2445df4f9b17ad2b417be66c3710",
    73  		"7b0c785e27e8ad3f8223207104725dd4",
    74  	},
    75  
    76  	// ECB-AES192
    77  	{
    78  		"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
    79  		"6bc1bee22e409f96e93d7e117393172a",
    80  		"bd334f1d6e45f25ff712a214571fa5cc",
    81  	},
    82  	{
    83  		"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
    84  		"ae2d8a571e03ac9c9eb76fac45af8e51",
    85  		"974104846d0ad3ad7734ecb3ecee4eef",
    86  	},
    87  	{
    88  		"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
    89  		"30c81c46a35ce411e5fbc1191a0a52ef",
    90  		"ef7afd2270e2e60adce0ba2face6444e",
    91  	},
    92  	{
    93  		"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
    94  		"f69f2445df4f9b17ad2b417be66c3710",
    95  		"9a4b41ba738d6c72fb16691603c18e0e",
    96  	},
    97  
    98  	// ECB-AES256
    99  	{
   100  		"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   101  		"6bc1bee22e409f96e93d7e117393172a",
   102  		"f3eed1bdb5d2a03c064b5a7e3db181f8",
   103  	},
   104  	{
   105  		"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   106  		"ae2d8a571e03ac9c9eb76fac45af8e51",
   107  		"591ccb10d410ed26dc5ba74a31362870",
   108  	},
   109  	{
   110  		"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   111  		"30c81c46a35ce411e5fbc1191a0a52ef",
   112  		"b6ed21b99ca6f4f9f153e7b1beafed1d",
   113  	},
   114  	{
   115  		"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   116  		"f69f2445df4f9b17ad2b417be66c3710",
   117  		"23304b7a39f9f3ff067d8d8f9e24ecc7",
   118  	},
   119  }
   120  
   121  func TestECB_SP800_38A(t *testing.T) {
   122  	for _, impl := range impls {
   123  		t.Logf("Testing implementation: %v\n", impl.name)
   124  		for i, vec := range ecbVectors {
   125  			key, err := hex.DecodeString(vec.key[:])
   126  			if err != nil {
   127  				t.Fatal(err)
   128  			}
   129  			pt, err := hex.DecodeString(vec.plaintext[:])
   130  			if err != nil {
   131  				t.Fatal(err)
   132  			}
   133  			ct, err := hex.DecodeString(vec.ciphertext[:])
   134  			if err != nil {
   135  				t.Fatal(err)
   136  			}
   137  
   138  			b := impl.ctor(key)
   139  
   140  			var dst [16]byte
   141  			b.Encrypt(dst[:], pt)
   142  			assertEqual(t, i, ct, dst[:])
   143  
   144  			b.Decrypt(dst[:], ct)
   145  			assertEqual(t, i, pt, dst[:])
   146  		}
   147  	}
   148  }
   149  
   150  var ctrVectors = []struct {
   151  	key        string
   152  	iv         string
   153  	plaintext  string
   154  	ciphertext string
   155  }{
   156  	// CTR-AES128
   157  	{
   158  		"2b7e151628aed2a6abf7158809cf4f3c",
   159  		"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
   160  		"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
   161  		"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee",
   162  	},
   163  	// CTR-AES192
   164  	{
   165  		"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
   166  		"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
   167  		"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
   168  		"1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e941e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050",
   169  	},
   170  	// CTR-AES256
   171  	{
   172  		"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   173  		"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
   174  		"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
   175  		"601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c52b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6",
   176  	},
   177  }
   178  
   179  func TestCTR_SP800_38A(t *testing.T) {
   180  	for _, impl := range impls {
   181  		t.Logf("Testing implementation: %v\n", impl.name)
   182  		for i, vec := range ctrVectors {
   183  			key, err := hex.DecodeString(vec.key[:])
   184  			if err != nil {
   185  				t.Fatal(err)
   186  			}
   187  			iv, err := hex.DecodeString(vec.iv[:])
   188  			if err != nil {
   189  				t.Fatal(err)
   190  			}
   191  			ct, err := hex.DecodeString(vec.ciphertext[:])
   192  			if err != nil {
   193  				t.Fatal(err)
   194  			}
   195  			pt, err := hex.DecodeString(vec.plaintext[:])
   196  			if err != nil {
   197  				t.Fatal(err)
   198  			}
   199  
   200  			b := impl.ctor(key)
   201  			dst := make([]byte, len(ct))
   202  
   203  			ctr := cipher.NewCTR(b, iv)
   204  			ctr.XORKeyStream(dst, pt)
   205  			assertEqual(t, i, ct, dst)
   206  		}
   207  	}
   208  }
   209  
   210  func TestCTR_keystream(t *testing.T) {
   211  	var iv [16]byte
   212  
   213  	for _, impl := range impls {
   214  		strideSz := 0
   215  		switch impl.name {
   216  		case "ct32":
   217  			strideSz = 2 * 16
   218  		case "ct64":
   219  			strideSz = 4 * 16
   220  		case "runtime":
   221  			// The CTR tests are tailored towards the bsaes CTR
   222  			// so there is not much sense in testing `crypto/aes`'s,
   223  			// when it's using AES-NI and assembly.
   224  			t.Logf("Skipping CTR tests: %v\n", impl.name)
   225  			continue
   226  		default:
   227  			panic("unable to determine stride")
   228  		}
   229  		t.Logf("Testing implementation: %v\n", impl.name)
   230  
   231  		key := make([]byte, 16)
   232  		if _, err := rand.Read(key[:]); err != nil {
   233  			t.Error(err)
   234  			t.Fail()
   235  		}
   236  
   237  		for sz := 0; sz <= strideSz; sz++ {
   238  			blk := impl.ctor(key[:])
   239  			ctr := cipher.NewCTR(blk, iv[:])
   240  
   241  			refBlk, _ := aes.NewCipher(key[:])
   242  			refCtr := cipher.NewCTR(refBlk, iv[:])
   243  
   244  			n := sz + strideSz + sz
   245  			src := make([]byte, n)
   246  			dst := make([]byte, n)
   247  			check := make([]byte, n)
   248  
   249  			if _, err := rand.Read(src[:]); err != nil {
   250  				t.Error(err)
   251  				t.Fail()
   252  			}
   253  
   254  			ctr.XORKeyStream(dst, src[:sz])
   255  			ctr.XORKeyStream(dst[sz:], src[sz:sz+strideSz])
   256  			ctr.XORKeyStream(dst[sz+strideSz:], src[sz+strideSz:])
   257  
   258  			refCtr.XORKeyStream(check, src)
   259  			assertEqual(t, sz, check, dst)
   260  		}
   261  	}
   262  }
   263  
   264  var cbcDecVectors = []struct {
   265  	key        string
   266  	iv         string
   267  	ciphertext string
   268  	plaintext  string
   269  }{
   270  	// CBC-AES128
   271  	{
   272  		"2b7e151628aed2a6abf7158809cf4f3c",
   273  		"000102030405060708090a0b0c0d0e0f",
   274  		"7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7",
   275  		"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
   276  	},
   277  	// CBC-AES192
   278  	{
   279  		"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
   280  		"000102030405060708090a0b0c0d0e0f",
   281  		"4f021db243bc633d7178183a9fa071e8b4d9ada9ad7dedf4e5e738763f69145a571b242012fb7ae07fa9baac3df102e008b0e27988598881d920a9e64f5615cd",
   282  		"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
   283  	},
   284  	// CBC-AES256
   285  	{
   286  
   287  		"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
   288  		"000102030405060708090a0b0c0d0e0f",
   289  		"f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b",
   290  		"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
   291  	},
   292  }
   293  
   294  func TestCBCDecrypt_SP800_38A(t *testing.T) {
   295  	for _, impl := range impls {
   296  		t.Logf("Testing implementation: %v\n", impl.name)
   297  		for i, vec := range cbcDecVectors {
   298  			key, err := hex.DecodeString(vec.key[:])
   299  			if err != nil {
   300  				t.Fatal(err)
   301  			}
   302  			iv, err := hex.DecodeString(vec.iv[:])
   303  			if err != nil {
   304  				t.Fatal(err)
   305  			}
   306  			ct, err := hex.DecodeString(vec.ciphertext[:])
   307  			if err != nil {
   308  				t.Fatal(err)
   309  			}
   310  			pt, err := hex.DecodeString(vec.plaintext[:])
   311  			if err != nil {
   312  				t.Fatal(err)
   313  			}
   314  
   315  			b := impl.ctor(key)
   316  			dst := make([]byte, len(ct))
   317  
   318  			cbc := cipher.NewCBCDecrypter(b, iv)
   319  			cbc.CryptBlocks(dst, ct)
   320  			assertEqual(t, i, pt, dst)
   321  		}
   322  	}
   323  }
   324  
   325  var gcmVectors = []struct {
   326  	k  string
   327  	iv string
   328  	a  string
   329  	p  string
   330  	c  string
   331  	t  string
   332  }{
   333  	// GCM-AES128
   334  	{
   335  		"00000000000000000000000000000000",
   336  		"000000000000000000000000",
   337  		"",
   338  		"",
   339  		"",
   340  		"58e2fccefa7e3061367f1d57a4e7455a",
   341  	},
   342  	{
   343  		"00000000000000000000000000000000",
   344  		"000000000000000000000000",
   345  		"",
   346  		"00000000000000000000000000000000",
   347  		"0388dace60b6a392f328c2b971b2fe78",
   348  		"ab6e47d42cec13bdf53a67b21257bddf",
   349  	},
   350  	{
   351  		"feffe9928665731c6d6a8f9467308308",
   352  		"cafebabefacedbaddecaf888",
   353  		"",
   354  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
   355  		"42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985",
   356  		"4d5c2af327cd64a62cf35abd2ba6fab4",
   357  	},
   358  	{
   359  		"feffe9928665731c6d6a8f9467308308",
   360  		"cafebabefacedbaddecaf888",
   361  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   362  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   363  		"42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091",
   364  		"5bc94fbc3221a5db94fae95ae7121a47",
   365  	},
   366  	{
   367  		"feffe9928665731c6d6a8f9467308308",
   368  		"cafebabefacedbad",
   369  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   370  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   371  		"61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598",
   372  		"3612d2e79e3b0785561be14aaca2fccb",
   373  	},
   374  	{
   375  		"feffe9928665731c6d6a8f9467308308",
   376  		"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
   377  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   378  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   379  		"8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5",
   380  		"619cc5aefffe0bfa462af43c1699d050",
   381  	},
   382  	// GCM-AES192
   383  	{
   384  		"000000000000000000000000000000000000000000000000",
   385  		"000000000000000000000000",
   386  		"",
   387  		"",
   388  		"",
   389  		"cd33b28ac773f74ba00ed1f312572435",
   390  	},
   391  	{
   392  		"000000000000000000000000000000000000000000000000",
   393  		"000000000000000000000000",
   394  		"",
   395  		"00000000000000000000000000000000",
   396  		"98e7247c07f0fe411c267e4384b0f600",
   397  		"2ff58d80033927ab8ef4d4587514f0fb",
   398  	},
   399  	{
   400  		"feffe9928665731c6d6a8f9467308308feffe9928665731c",
   401  		"cafebabefacedbaddecaf888",
   402  		"",
   403  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
   404  		"3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256",
   405  		"9924a7c8587336bfb118024db8674a14",
   406  	},
   407  	{
   408  		"feffe9928665731c6d6a8f9467308308feffe9928665731c",
   409  		"cafebabefacedbaddecaf888",
   410  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   411  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   412  		"3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710",
   413  		"2519498e80f1478f37ba55bd6d27618c",
   414  	},
   415  	{
   416  		"feffe9928665731c6d6a8f9467308308feffe9928665731c",
   417  		"cafebabefacedbad",
   418  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   419  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   420  		"0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
   421  		"65dcc57fcf623a24094fcca40d3533f8",
   422  	},
   423  	{
   424  		"feffe9928665731c6d6a8f9467308308feffe9928665731c",
   425  		"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
   426  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   427  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   428  		"d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b",
   429  		"dcf566ff291c25bbb8568fc3d376a6d9",
   430  	},
   431  	// GCM-AES256
   432  	{
   433  		"0000000000000000000000000000000000000000000000000000000000000000",
   434  		"000000000000000000000000",
   435  		"",
   436  		"",
   437  		"",
   438  		"530f8afbc74536b9a963b4f1c4cb738b",
   439  	},
   440  	{
   441  		"0000000000000000000000000000000000000000000000000000000000000000",
   442  		"000000000000000000000000",
   443  		"",
   444  		"00000000000000000000000000000000",
   445  		"cea7403d4d606b6e074ec5d3baf39d18",
   446  		"d0d1c8a799996bf0265b98b5d48ab919",
   447  	},
   448  	{
   449  		"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
   450  		"cafebabefacedbaddecaf888",
   451  		"",
   452  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
   453  		"522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
   454  		"b094dac5d93471bdec1a502270e3cc6c",
   455  	},
   456  	{
   457  		"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
   458  		"cafebabefacedbaddecaf888",
   459  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   460  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   461  		"522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
   462  		"76fc6ece0f4e1768cddf8853bb2d551b",
   463  	},
   464  	{
   465  		"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
   466  		"cafebabefacedbad",
   467  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   468  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   469  		"c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f",
   470  		"3a337dbf46a792c45e454913fe2ea8f2",
   471  	},
   472  	{
   473  		"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
   474  		"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
   475  		"feedfacedeadbeeffeedfacedeadbeefabaddad2",
   476  		"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
   477  		"5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f",
   478  		"a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
   479  	},
   480  }
   481  
   482  func TestGCM(t *testing.T) {
   483  	for _, impl := range impls {
   484  		t.Logf("Testing implementation: %v\n", impl.name)
   485  		for i, vec := range gcmVectors {
   486  			key, err := hex.DecodeString(vec.k[:])
   487  			if err != nil {
   488  				t.Fatal(err)
   489  			}
   490  			iv, err := hex.DecodeString(vec.iv[:])
   491  			if err != nil {
   492  				t.Fatal(err)
   493  			}
   494  			a, err := hex.DecodeString(vec.a[:])
   495  			if err != nil {
   496  				t.Fatal(err)
   497  			}
   498  			p, err := hex.DecodeString(vec.p[:])
   499  			if err != nil {
   500  				t.Fatal(err)
   501  			}
   502  			c, err := hex.DecodeString(vec.c[:])
   503  			if err != nil {
   504  				t.Fatal(err)
   505  			}
   506  			tag, err := hex.DecodeString(vec.t[:])
   507  			if err != nil {
   508  				t.Fatal(err)
   509  			}
   510  			sealOut := make([]byte, 0, len(c)+len(tag))
   511  			sealOut = append(sealOut, c...)
   512  			sealOut = append(sealOut, tag...)
   513  
   514  			b := impl.ctor(key[:])
   515  			g, err := cipher.NewGCMWithNonceSize(b, len(iv))
   516  			if err != nil {
   517  				t.Fatal(err)
   518  			}
   519  
   520  			ct := g.Seal(nil, iv, p, a)
   521  			assertEqual(t, i, sealOut, ct)
   522  
   523  			pt, err := g.Open(nil, iv, ct, a)
   524  			if err != nil {
   525  				t.Fatal(err)
   526  			}
   527  			assertEqual(t, i, p, pt)
   528  		}
   529  	}
   530  }
   531  
   532  func assertEqual(t *testing.T, idx int, expected, actual []byte) {
   533  	if !bytes.Equal(expected, actual) {
   534  		for i, v := range actual {
   535  			if expected[i] != v {
   536  				t.Errorf("[%d] first mismatch at offset: %d (%02x != %02x)", idx, i, expected[i], v)
   537  				break
   538  			}
   539  		}
   540  		t.Errorf("expected: %s", hex.Dump(expected))
   541  		t.Errorf("actual: %s", hex.Dump(actual))
   542  		t.FailNow()
   543  	}
   544  }
   545  
   546  var ecbBenchOutput [16]byte
   547  
   548  func doBenchECB(b *testing.B, impl *Impl, ksz int) {
   549  	var src, dst, check [16]byte
   550  
   551  	key := make([]byte, ksz)
   552  	if _, err := rand.Read(key[:]); err != nil {
   553  		b.Error(err)
   554  		b.Fail()
   555  	}
   556  
   557  	blk := impl.ctor(key[:])
   558  
   559  	b.SetBytes(16)
   560  	b.ResetTimer()
   561  	for i := 0; i < b.N; i++ {
   562  		b.StartTimer()
   563  		blk.Encrypt(dst[:], src[:])
   564  		b.StopTimer()
   565  
   566  		// Check forward/back because, why not.
   567  		blk.Decrypt(check[:], dst[:])
   568  		if !bytes.Equal(check[:], src[:]) {
   569  			b.Fatalf("decrypt produced invalid output")
   570  		}
   571  		copy(src[:], dst[:])
   572  	}
   573  	copy(ecbBenchOutput[:], dst[:])
   574  }
   575  
   576  var benchOutput []byte
   577  
   578  func doBenchCTR(b *testing.B, impl *Impl, ksz, n int) {
   579  	var iv [16]byte
   580  
   581  	key := make([]byte, ksz)
   582  	if _, err := rand.Read(key[:]); err != nil {
   583  		b.Error(err)
   584  		b.Fail()
   585  	}
   586  
   587  	blk := impl.ctor(key[:])
   588  	ctr := cipher.NewCTR(blk, iv[:])
   589  
   590  	src := make([]byte, n)
   591  	dst := make([]byte, n)
   592  
   593  	b.SetBytes(int64(n))
   594  	b.ResetTimer()
   595  	for i := 0; i < b.N; i++ {
   596  		ctr.XORKeyStream(dst, src)
   597  	}
   598  	benchOutput = dst
   599  }
   600  
   601  func doBenchCBC(b *testing.B, impl *Impl, ksz, n int) {
   602  	var iv [16]byte
   603  	key := make([]byte, ksz)
   604  
   605  	if _, err := rand.Read(key[:]); err != nil {
   606  		b.Error(err)
   607  		b.Fail()
   608  	}
   609  
   610  	blk := impl.ctor(key[:])
   611  	cbc := cipher.NewCBCDecrypter(blk, iv[:])
   612  
   613  	src := make([]byte, n)
   614  	dst := make([]byte, n)
   615  
   616  	b.SetBytes(int64(n))
   617  	b.ResetTimer()
   618  	for i := 0; i < b.N; i++ {
   619  		cbc.CryptBlocks(dst, src)
   620  	}
   621  	benchOutput = dst
   622  }
   623  
   624  func doBenchGCM(b *testing.B, impl *Impl, ksz, n int) {
   625  	var iv [96 / 8]byte
   626  	key := make([]byte, ksz)
   627  
   628  	if _, err := rand.Read(key[:]); err != nil {
   629  		b.Error(err)
   630  		b.Fail()
   631  	}
   632  
   633  	blk := impl.ctor(key[:])
   634  	gcm, err := cipher.NewGCM(blk)
   635  	if err != nil {
   636  		b.Error(err)
   637  		b.Fail()
   638  	}
   639  
   640  	src := make([]byte, n)
   641  	var dst []byte
   642  
   643  	b.SetBytes(int64(n))
   644  	b.ResetTimer()
   645  	for i := 0; i < b.N; i++ {
   646  		dst = gcm.Seal(nil, iv[:], src, nil)
   647  	}
   648  	benchOutput = dst
   649  }
   650  
   651  func implIsNative(impl *Impl) bool {
   652  	return impl == nativeImpl || impl == implRuntime
   653  }
   654  
   655  func doBench(b *testing.B, impl *Impl) {
   656  	if testing.Short() && !implIsNative(impl) {
   657  		b.SkipNow()
   658  	}
   659  
   660  	b.SetParallelism(1) // We want per-core figures.
   661  
   662  	b.Run("ECB-AES128", func(b *testing.B) { doBenchECB(b, implCt32, 16) })
   663  	if !testing.Short() { // No one cares about this mode.
   664  		b.Run("ECB-AES192", func(b *testing.B) { doBenchECB(b, implCt32, 24) })
   665  	}
   666  	b.Run("ECB-AES256", func(b *testing.B) { doBenchECB(b, implCt32, 32) })
   667  
   668  	for _, sz := range []int{16, 64, 256, 1024, 8192, 16384} {
   669  		n := fmt.Sprintf("CTR-AES128_%d", sz)
   670  		b.Run(n, func(b *testing.B) { doBenchCTR(b, impl, 16, sz) })
   671  	}
   672  	for _, sz := range []int{16, 64, 256, 1024, 8192, 16384} {
   673  		n := fmt.Sprintf("DecryptCBC-AES128_%d", sz)
   674  		b.Run(n, func(b *testing.B) { doBenchCBC(b, impl, 16, sz) })
   675  	}
   676  	for _, sz := range []int{16, 64, 256, 1024, 8192, 16384} {
   677  		n := fmt.Sprintf("GCM-AES128_%d", sz)
   678  		b.Run(n, func(b *testing.B) { doBenchGCM(b, impl, 16, sz) })
   679  	}
   680  }
   681  
   682  func Benchmark_ct32(b *testing.B) {
   683  	doBench(b, implCt32)
   684  }
   685  
   686  func Benchmark_ct64(b *testing.B) {
   687  	doBench(b, implCt64)
   688  }
   689  
   690  func Benchmark_runtime(b *testing.B) {
   691  	if !useCryptoAES {
   692  		b.SkipNow()
   693  	}
   694  	doBench(b, implRuntime)
   695  }
   696  
   697  func init() {
   698  	maxUintptr := uint64(^uintptr(0))
   699  	switch maxUintptr {
   700  	case math.MaxUint32:
   701  		nativeImpl = implCt32
   702  	case math.MaxUint64:
   703  		nativeImpl = implCt64
   704  	default:
   705  		panic("bsaes: unsupported architecture")
   706  	}
   707  	if useCryptoAES {
   708  		impls = append(impls, implRuntime)
   709  	}
   710  }