You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

224 lines
7.8 KiB

  1. /*
  2. *
  3. * Copyright 2018 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package conn
  19. import (
  20. "bytes"
  21. "testing"
  22. core "google.golang.org/grpc/credentials/alts/internal"
  23. )
  24. // cryptoTestVector is struct for a GCM test vector
  25. type cryptoTestVector struct {
  26. key, counter, plaintext, ciphertext, tag []byte
  27. allocateDst bool
  28. }
  29. // getGCMCryptoPair outputs a client/server pair on aes128gcm.
  30. func getGCMCryptoPair(key []byte, counter []byte, t *testing.T) (ALTSRecordCrypto, ALTSRecordCrypto) {
  31. client, err := NewAES128GCM(core.ClientSide, key)
  32. if err != nil {
  33. t.Fatalf("NewAES128GCM(ClientSide, key) = %v", err)
  34. }
  35. server, err := NewAES128GCM(core.ServerSide, key)
  36. if err != nil {
  37. t.Fatalf("NewAES128GCM(ServerSide, key) = %v", err)
  38. }
  39. // set counter if provided.
  40. if counter != nil {
  41. if CounterSide(counter) == core.ClientSide {
  42. client.(*aes128gcm).outCounter = CounterFromValue(counter, overflowLenAES128GCM)
  43. server.(*aes128gcm).inCounter = CounterFromValue(counter, overflowLenAES128GCM)
  44. } else {
  45. server.(*aes128gcm).outCounter = CounterFromValue(counter, overflowLenAES128GCM)
  46. client.(*aes128gcm).inCounter = CounterFromValue(counter, overflowLenAES128GCM)
  47. }
  48. }
  49. return client, server
  50. }
  51. func testGCMEncryptionDecryption(sender ALTSRecordCrypto, receiver ALTSRecordCrypto, test *cryptoTestVector, withCounter bool, t *testing.T) {
  52. // Ciphertext is: counter + encrypted text + tag.
  53. ciphertext := []byte(nil)
  54. if withCounter {
  55. ciphertext = append(ciphertext, test.counter...)
  56. }
  57. ciphertext = append(ciphertext, test.ciphertext...)
  58. ciphertext = append(ciphertext, test.tag...)
  59. // Decrypt.
  60. if got, err := receiver.Decrypt(nil, ciphertext); err != nil || !bytes.Equal(got, test.plaintext) {
  61. t.Errorf("key=%v\ncounter=%v\ntag=%v\nciphertext=%v\nDecrypt = %v, %v\nwant: %v",
  62. test.key, test.counter, test.tag, test.ciphertext, got, err, test.plaintext)
  63. }
  64. // Encrypt.
  65. var dst []byte
  66. if test.allocateDst {
  67. dst = make([]byte, len(test.plaintext)+sender.EncryptionOverhead())
  68. }
  69. if got, err := sender.Encrypt(dst[:0], test.plaintext); err != nil || !bytes.Equal(got, ciphertext) {
  70. t.Errorf("key=%v\ncounter=%v\nplaintext=%v\nEncrypt = %v, %v\nwant: %v",
  71. test.key, test.counter, test.plaintext, got, err, ciphertext)
  72. }
  73. }
  74. // Test encrypt and decrypt using test vectors for aes128gcm.
  75. func TestAES128GCMEncrypt(t *testing.T) {
  76. for _, test := range []cryptoTestVector{
  77. {
  78. key: dehex("11754cd72aec309bf52f7687212e8957"),
  79. counter: dehex("3c819d9a9bed087615030b65"),
  80. plaintext: nil,
  81. ciphertext: nil,
  82. tag: dehex("250327c674aaf477aef2675748cf6971"),
  83. allocateDst: false,
  84. },
  85. {
  86. key: dehex("ca47248ac0b6f8372a97ac43508308ed"),
  87. counter: dehex("ffd2b598feabc9019262d2be"),
  88. plaintext: nil,
  89. ciphertext: nil,
  90. tag: dehex("60d20404af527d248d893ae495707d1a"),
  91. allocateDst: false,
  92. },
  93. {
  94. key: dehex("7fddb57453c241d03efbed3ac44e371c"),
  95. counter: dehex("ee283a3fc75575e33efd4887"),
  96. plaintext: dehex("d5de42b461646c255c87bd2962d3b9a2"),
  97. ciphertext: dehex("2ccda4a5415cb91e135c2a0f78c9b2fd"),
  98. tag: dehex("b36d1df9b9d5e596f83e8b7f52971cb3"),
  99. allocateDst: false,
  100. },
  101. {
  102. key: dehex("ab72c77b97cb5fe9a382d9fe81ffdbed"),
  103. counter: dehex("54cc7dc2c37ec006bcc6d1da"),
  104. plaintext: dehex("007c5e5b3e59df24a7c355584fc1518d"),
  105. ciphertext: dehex("0e1bde206a07a9c2c1b65300f8c64997"),
  106. tag: dehex("2b4401346697138c7a4891ee59867d0c"),
  107. allocateDst: false,
  108. },
  109. {
  110. key: dehex("11754cd72aec309bf52f7687212e8957"),
  111. counter: dehex("3c819d9a9bed087615030b65"),
  112. plaintext: nil,
  113. ciphertext: nil,
  114. tag: dehex("250327c674aaf477aef2675748cf6971"),
  115. allocateDst: true,
  116. },
  117. {
  118. key: dehex("ca47248ac0b6f8372a97ac43508308ed"),
  119. counter: dehex("ffd2b598feabc9019262d2be"),
  120. plaintext: nil,
  121. ciphertext: nil,
  122. tag: dehex("60d20404af527d248d893ae495707d1a"),
  123. allocateDst: true,
  124. },
  125. {
  126. key: dehex("7fddb57453c241d03efbed3ac44e371c"),
  127. counter: dehex("ee283a3fc75575e33efd4887"),
  128. plaintext: dehex("d5de42b461646c255c87bd2962d3b9a2"),
  129. ciphertext: dehex("2ccda4a5415cb91e135c2a0f78c9b2fd"),
  130. tag: dehex("b36d1df9b9d5e596f83e8b7f52971cb3"),
  131. allocateDst: true,
  132. },
  133. {
  134. key: dehex("ab72c77b97cb5fe9a382d9fe81ffdbed"),
  135. counter: dehex("54cc7dc2c37ec006bcc6d1da"),
  136. plaintext: dehex("007c5e5b3e59df24a7c355584fc1518d"),
  137. ciphertext: dehex("0e1bde206a07a9c2c1b65300f8c64997"),
  138. tag: dehex("2b4401346697138c7a4891ee59867d0c"),
  139. allocateDst: true,
  140. },
  141. } {
  142. // Test encryption and decryption for aes128gcm.
  143. client, server := getGCMCryptoPair(test.key, test.counter, t)
  144. if CounterSide(test.counter) == core.ClientSide {
  145. testGCMEncryptionDecryption(client, server, &test, false, t)
  146. } else {
  147. testGCMEncryptionDecryption(server, client, &test, false, t)
  148. }
  149. }
  150. }
  151. func testGCMEncryptRoundtrip(client ALTSRecordCrypto, server ALTSRecordCrypto, t *testing.T) {
  152. // Encrypt.
  153. const plaintext = "This is plaintext."
  154. var err error
  155. buf := []byte(plaintext)
  156. buf, err = client.Encrypt(buf[:0], buf)
  157. if err != nil {
  158. t.Fatal("Encrypting with client-side context: unexpected error", err, "\n",
  159. "Plaintext:", []byte(plaintext))
  160. }
  161. // Encrypt a second message.
  162. const plaintext2 = "This is a second plaintext."
  163. buf2 := []byte(plaintext2)
  164. buf2, err = client.Encrypt(buf2[:0], buf2)
  165. if err != nil {
  166. t.Fatal("Encrypting with client-side context: unexpected error", err, "\n",
  167. "Plaintext:", []byte(plaintext2))
  168. }
  169. // Decryption fails: cannot decrypt second message before first.
  170. if got, err := server.Decrypt(nil, buf2); err == nil {
  171. t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n",
  172. " Original plaintext:", []byte(plaintext2), "\n",
  173. " Ciphertext:", buf2, "\n",
  174. " Decrypted plaintext:", got)
  175. }
  176. // Decryption fails: wrong counter space.
  177. if got, err := client.Decrypt(nil, buf); err == nil {
  178. t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want counter space error:\n",
  179. " Original plaintext:", []byte(plaintext), "\n",
  180. " Ciphertext:", buf, "\n",
  181. " Decrypted plaintext:", got)
  182. }
  183. // Decrypt first message.
  184. ciphertext := append([]byte(nil), buf...)
  185. buf, err = server.Decrypt(buf[:0], buf)
  186. if err != nil || string(buf) != plaintext {
  187. t.Fatal("Decrypting client-side ciphertext with a server-side context did not produce original content:\n",
  188. " Original plaintext:", []byte(plaintext), "\n",
  189. " Ciphertext:", ciphertext, "\n",
  190. " Decryption error:", err, "\n",
  191. " Decrypted plaintext:", buf)
  192. }
  193. // Decryption fails: replay attack.
  194. if got, err := server.Decrypt(nil, buf); err == nil {
  195. t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n",
  196. " Original plaintext:", []byte(plaintext), "\n",
  197. " Ciphertext:", buf, "\n",
  198. " Decrypted plaintext:", got)
  199. }
  200. }
  201. // Test encrypt and decrypt on roundtrip messages for aes128gcm.
  202. func TestAES128GCMEncryptRoundtrip(t *testing.T) {
  203. // Test for aes128gcm.
  204. key := make([]byte, 16)
  205. client, server := getGCMCryptoPair(key, nil, t)
  206. testGCMEncryptRoundtrip(client, server, t)
  207. }