Grain128AEADEngine.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.IO;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
  8. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
  9. {
  10. public sealed class Grain128AeadEngine
  11. : IAeadCipher
  12. {
  13. /**
  14. * Constants
  15. */
  16. private static readonly int STATE_SIZE = 4;
  17. /**
  18. * Variables to hold the state of the engine during encryption and
  19. * decryption
  20. */
  21. private byte[] workingKey;
  22. private byte[] workingIV;
  23. private uint[] lfsr;
  24. private uint[] nfsr;
  25. private uint[] authAcc;
  26. private uint[] authSr;
  27. private bool initialised = false;
  28. private bool aadFinished = false;
  29. private MemoryStream aadData = new MemoryStream();
  30. private byte[] mac;
  31. public string AlgorithmName => "Grain-128AEAD";
  32. /**
  33. * Initialize a Grain-128AEAD cipher.
  34. *
  35. * @param forEncryption Whether or not we are for encryption.
  36. * @param param The parameters required to set up the cipher.
  37. * @throws ArgumentException If the params argument is inappropriate.
  38. */
  39. public void Init(bool forEncryption, ICipherParameters param)
  40. {
  41. /*
  42. * Grain encryption and decryption is completely symmetrical, so the
  43. * 'forEncryption' is irrelevant.
  44. */
  45. if (!(param is ParametersWithIV ivParams))
  46. throw new ArgumentException("Grain-128AEAD Init parameters must include an IV");
  47. byte[] iv = ivParams.GetIV();
  48. if (iv == null || iv.Length != 12)
  49. throw new ArgumentException("Grain-128AEAD requires exactly 12 bytes of IV");
  50. if (!(ivParams.Parameters is KeyParameter key))
  51. throw new ArgumentException("Grain-128AEAD Init parameters must include a key");
  52. byte[] keyBytes = key.GetKey();
  53. if (keyBytes.Length != 16)
  54. throw new ArgumentException("Grain-128AEAD key must be 128 bits long");
  55. /*
  56. * Initialize variables.
  57. */
  58. workingIV = new byte[keyBytes.Length];
  59. workingKey = keyBytes;
  60. lfsr = new uint[STATE_SIZE];
  61. nfsr = new uint[STATE_SIZE];
  62. authAcc = new uint[2];
  63. authSr = new uint[2];
  64. Array.Copy(iv, 0, workingIV, 0, iv.Length);
  65. Reset();
  66. }
  67. /**
  68. * 320 clocks initialization phase.
  69. */
  70. private void InitGrain()
  71. {
  72. for (int i = 0; i < 320; ++i)
  73. {
  74. uint outputZ = GetOutput();
  75. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0] ^ outputZ) & 1);
  76. lfsr = Shift(lfsr, (GetOutputLFSR() ^ outputZ) & 1);
  77. }
  78. for (int quotient = 0; quotient < 8; ++quotient)
  79. {
  80. for (int remainder = 0; remainder < 8; ++remainder)
  81. {
  82. uint outputZ = GetOutput();
  83. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0] ^ outputZ ^ (uint)((workingKey[quotient]) >> remainder)) & 1);
  84. lfsr = Shift(lfsr, (GetOutputLFSR() ^ outputZ ^ (uint)((workingKey[quotient + 8]) >> remainder)) & 1);
  85. }
  86. }
  87. for (int quotient = 0; quotient < 2; ++quotient)
  88. {
  89. for (int remainder = 0; remainder < 32; ++remainder)
  90. {
  91. uint outputZ = GetOutput();
  92. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  93. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  94. authAcc[quotient] |= outputZ << remainder;
  95. }
  96. }
  97. for (int quotient = 0; quotient < 2; ++quotient)
  98. {
  99. for (int remainder = 0; remainder < 32; ++remainder)
  100. {
  101. uint outputZ = GetOutput();
  102. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  103. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  104. authSr[quotient] |= outputZ << remainder;
  105. }
  106. }
  107. initialised = true;
  108. }
  109. /**
  110. * Get output from non-linear function g(x).
  111. *
  112. * @return Output from NFSR.
  113. */
  114. private uint GetOutputNFSR()
  115. {
  116. uint b0 = nfsr[0];
  117. uint b3 = nfsr[0] >> 3;
  118. uint b11 = nfsr[0] >> 11;
  119. uint b13 = nfsr[0] >> 13;
  120. uint b17 = nfsr[0] >> 17;
  121. uint b18 = nfsr[0] >> 18;
  122. uint b22 = nfsr[0] >> 22;
  123. uint b24 = nfsr[0] >> 24;
  124. uint b25 = nfsr[0] >> 25;
  125. uint b26 = nfsr[0] >> 26;
  126. uint b27 = nfsr[0] >> 27;
  127. uint b40 = nfsr[1] >> 8;
  128. uint b48 = nfsr[1] >> 16;
  129. uint b56 = nfsr[1] >> 24;
  130. uint b59 = nfsr[1] >> 27;
  131. uint b61 = nfsr[1] >> 29;
  132. uint b65 = nfsr[2] >> 1;
  133. uint b67 = nfsr[2] >> 3;
  134. uint b68 = nfsr[2] >> 4;
  135. uint b70 = nfsr[2] >> 6;
  136. uint b78 = nfsr[2] >> 14;
  137. uint b82 = nfsr[2] >> 18;
  138. uint b84 = nfsr[2] >> 20;
  139. uint b88 = nfsr[2] >> 24;
  140. uint b91 = nfsr[2] >> 27;
  141. uint b92 = nfsr[2] >> 28;
  142. uint b93 = nfsr[2] >> 29;
  143. uint b95 = nfsr[2] >> 31;
  144. uint b96 = nfsr[3];
  145. return (b0 ^ b26 ^ b56 ^ b91 ^ b96 ^ b3 & b67 ^ b11 & b13 ^ b17 & b18
  146. ^ b27 & b59 ^ b40 & b48 ^ b61 & b65 ^ b68 & b84 ^ b22 & b24 & b25 ^ b70 & b78 & b82 ^ b88 & b92 & b93 & b95) & 1;
  147. }
  148. /**
  149. * Get output from linear function f(x).
  150. *
  151. * @return Output from LFSR.
  152. */
  153. private uint GetOutputLFSR()
  154. {
  155. uint s0 = lfsr[0];
  156. uint s7 = lfsr[0] >> 7;
  157. uint s38 = lfsr[1] >> 6;
  158. uint s70 = lfsr[2] >> 6;
  159. uint s81 = lfsr[2] >> 17;
  160. uint s96 = lfsr[3];
  161. return (s0 ^ s7 ^ s38 ^ s70 ^ s81 ^ s96) & 1;
  162. }
  163. /**
  164. * Get output from output function h(x).
  165. *
  166. * @return y_t.
  167. */
  168. private uint GetOutput()
  169. {
  170. uint b2 = nfsr[0] >> 2;
  171. uint b12 = nfsr[0] >> 12;
  172. uint b15 = nfsr[0] >> 15;
  173. uint b36 = nfsr[1] >> 4;
  174. uint b45 = nfsr[1] >> 13;
  175. uint b64 = nfsr[2];
  176. uint b73 = nfsr[2] >> 9;
  177. uint b89 = nfsr[2] >> 25;
  178. uint b95 = nfsr[2] >> 31;
  179. uint s8 = lfsr[0] >> 8;
  180. uint s13 = lfsr[0] >> 13;
  181. uint s20 = lfsr[0] >> 20;
  182. uint s42 = lfsr[1] >> 10;
  183. uint s60 = lfsr[1] >> 28;
  184. uint s79 = lfsr[2] >> 15;
  185. uint s93 = lfsr[2] >> 29;
  186. uint s94 = lfsr[2] >> 30;
  187. return ((b12 & s8) ^ (s13 & s20) ^ (b95 & s42) ^ (s60 & s79) ^ (b12 & b95 & s94) ^ s93
  188. ^ b2 ^ b15 ^ b36 ^ b45 ^ b64 ^ b73 ^ b89) & 1;
  189. }
  190. /**
  191. * Shift array 1 bit and add val to index.Length - 1.
  192. *
  193. * @param array The array to shift.
  194. * @param val The value to shift in.
  195. * @return The shifted array with val added to index.Length - 1.
  196. */
  197. private uint[] Shift(uint[] array, uint val)
  198. {
  199. array[0] = (array[0] >> 1) | (array[1] << 31);
  200. array[1] = (array[1] >> 1) | (array[2] << 31);
  201. array[2] = (array[2] >> 1) | (array[3] << 31);
  202. array[3] = (array[3] >> 1) | (val << 31);
  203. return array;
  204. }
  205. /**
  206. * Set keys, reset cipher.
  207. *
  208. * @param keyBytes The key.
  209. * @param ivBytes The IV.
  210. */
  211. private void SetKey(byte[] keyBytes, byte[] ivBytes)
  212. {
  213. ivBytes[12] = 0xFF;
  214. ivBytes[13] = 0xFF;
  215. ivBytes[14] = 0xFF;
  216. ivBytes[15] = 0x7F;
  217. workingKey = keyBytes;
  218. workingIV = ivBytes;
  219. /*
  220. * Load NFSR and LFSR
  221. */
  222. Pack.LE_To_UInt32(workingKey, 0, nfsr);
  223. Pack.LE_To_UInt32(workingIV, 0, lfsr);
  224. }
  225. public int ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
  226. {
  227. Check.DataLength(input, inOff, len, "input buffer too short");
  228. Check.OutputLength(output, outOff, len, "output buffer too short");
  229. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  230. return ProcessBytes(input.AsSpan(inOff, len), output.AsSpan(outOff));
  231. #else
  232. if (!initialised)
  233. throw new ArgumentException(AlgorithmName + " not initialised");
  234. if (!aadFinished)
  235. {
  236. DoProcessAADBytes(aadData.GetBuffer(), 0, (int)aadData.Length);
  237. aadFinished = true;
  238. }
  239. GetKeyStream(input, inOff, len, output, outOff);
  240. return len;
  241. #endif
  242. }
  243. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  244. public int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
  245. {
  246. Check.OutputLength(output, input.Length, "output buffer too short");
  247. if (!initialised)
  248. throw new ArgumentException(AlgorithmName + " not initialised");
  249. if (!aadFinished)
  250. {
  251. DoProcessAADBytes(aadData.GetBuffer(), 0, (int)aadData.Length);
  252. aadFinished = true;
  253. }
  254. GetKeyStream(input, output);
  255. return input.Length;
  256. }
  257. #endif
  258. public void Reset()
  259. {
  260. Reset(true);
  261. }
  262. private void Reset(bool clearMac)
  263. {
  264. if (clearMac)
  265. {
  266. this.mac = null;
  267. }
  268. this.aadData.SetLength(0);
  269. this.aadFinished = false;
  270. SetKey(workingKey, workingIV);
  271. InitGrain();
  272. }
  273. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  274. private void GetKeyStream(ReadOnlySpan<byte> input, Span<byte> output)
  275. {
  276. int len = input.Length;
  277. for (int i = 0; i < len; ++i)
  278. {
  279. uint cc = 0, input_i = input[i];
  280. for (int j = 0; j < 8; ++j)
  281. {
  282. uint outputZ = GetOutput();
  283. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  284. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  285. uint input_i_j = (input_i >> j) & 1U;
  286. cc |= (input_i_j ^ outputZ) << j;
  287. //if (input_i_j != 0)
  288. //{
  289. // Accumulate();
  290. //}
  291. uint mask = 0U - input_i_j;
  292. authAcc[0] ^= authSr[0] & mask;
  293. authAcc[1] ^= authSr[1] & mask;
  294. AuthShift(GetOutput());
  295. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  296. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  297. }
  298. output[i] = (byte)cc;
  299. }
  300. }
  301. #else
  302. private void GetKeyStream(byte[] input, int inOff, int len, byte[] ciphertext, int outOff)
  303. {
  304. for (int i = 0; i < len; ++i)
  305. {
  306. uint cc = 0, input_i = input[inOff + i];
  307. for (int j = 0; j < 8; ++j)
  308. {
  309. uint outputZ = GetOutput();
  310. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  311. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  312. uint input_i_j = (input_i >> j) & 1U;
  313. cc |= (input_i_j ^ outputZ) << j;
  314. //if (input_i_j != 0)
  315. //{
  316. // Accumulate();
  317. //}
  318. uint mask = 0U - input_i_j;
  319. authAcc[0] ^= authSr[0] & mask;
  320. authAcc[1] ^= authSr[1] & mask;
  321. AuthShift(GetOutput());
  322. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  323. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  324. }
  325. ciphertext[outOff + i] = (byte)cc;
  326. }
  327. }
  328. #endif
  329. public byte ReturnByte(byte input)
  330. {
  331. if (!initialised)
  332. throw new ArgumentException(AlgorithmName + " not initialised");
  333. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  334. Span<byte> plaintext = stackalloc byte[1]{ input };
  335. Span<byte> ciphertext = stackalloc byte[1];
  336. GetKeyStream(plaintext, ciphertext);
  337. return ciphertext[0];
  338. #else
  339. byte[] plaintext = new byte[1]{ input };
  340. byte[] ciphertext = new byte[1];
  341. GetKeyStream(plaintext, 0, 1, ciphertext, 0);
  342. return ciphertext[0];
  343. #endif
  344. }
  345. public void ProcessAadByte(byte input)
  346. {
  347. if (aadFinished)
  348. throw new ArgumentException("associated data must be added before plaintext/ciphertext");
  349. aadData.WriteByte(input);
  350. }
  351. public void ProcessAadBytes(byte[] input, int inOff, int len)
  352. {
  353. if (aadFinished)
  354. throw new ArgumentException("associated data must be added before plaintext/ciphertext");
  355. aadData.Write(input, inOff, len);
  356. }
  357. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  358. public void ProcessAadBytes(ReadOnlySpan<byte> input)
  359. {
  360. if (aadFinished)
  361. throw new ArgumentException("associated data must be added before plaintext/ciphertext");
  362. aadData.Write(input);
  363. }
  364. #endif
  365. private void Accumulate()
  366. {
  367. authAcc[0] ^= authSr[0];
  368. authAcc[1] ^= authSr[1];
  369. }
  370. private void AuthShift(uint val)
  371. {
  372. authSr[0] = (authSr[0] >> 1) | (authSr[1] << 31);
  373. authSr[1] = (authSr[1] >> 1) | (val << 31);
  374. }
  375. public int ProcessByte(byte input, byte[] output, int outOff)
  376. {
  377. return ProcessBytes(new byte[]{ input }, 0, 1, output, outOff);
  378. }
  379. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  380. public int ProcessByte(byte input, Span<byte> output)
  381. {
  382. return ProcessBytes(stackalloc byte[1]{ input }, output);
  383. }
  384. #endif
  385. private void DoProcessAADBytes(byte[] input, int inOff, int len)
  386. {
  387. byte[] ader;
  388. int aderlen;
  389. //encodeDer
  390. if (len < 128)
  391. {
  392. ader = new byte[1 + len];
  393. ader[0] = (byte)len;
  394. aderlen = 0;
  395. }
  396. else
  397. {
  398. // aderlen is the highest bit position divided by 8
  399. aderlen = LenLength(len);
  400. ader = new byte[aderlen + 1 + len];
  401. ader[0] = (byte)(0x80 | (uint)aderlen);
  402. uint tmp = (uint)len;
  403. for (int i = 0; i < aderlen; ++i)
  404. {
  405. ader[1 + i] = (byte)tmp;
  406. tmp >>= 8;
  407. }
  408. }
  409. for (int i = 0; i < len; ++i)
  410. {
  411. ader[1 + aderlen + i] = input[inOff + i];
  412. }
  413. for (int i = 0; i < ader.Length; ++i)
  414. {
  415. uint ader_i = ader[i];
  416. for (int j = 0; j < 8; ++j)
  417. {
  418. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  419. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  420. uint ader_i_j = (ader_i >> j) & 1U;
  421. //if (ader_i_j != 0)
  422. //{
  423. // Accumulate();
  424. //}
  425. uint mask = 0U - ader_i_j;
  426. authAcc[0] ^= authSr[0] & mask;
  427. authAcc[1] ^= authSr[1] & mask;
  428. AuthShift(GetOutput());
  429. nfsr = Shift(nfsr, (GetOutputNFSR() ^ lfsr[0]) & 1);
  430. lfsr = Shift(lfsr, (GetOutputLFSR()) & 1);
  431. }
  432. }
  433. }
  434. public int DoFinal(byte[] output, int outOff)
  435. {
  436. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  437. return DoFinal(output.AsSpan(outOff));
  438. #else
  439. if (!aadFinished)
  440. {
  441. DoProcessAADBytes(aadData.GetBuffer(), 0, (int)aadData.Length);
  442. aadFinished = true;
  443. }
  444. Accumulate();
  445. this.mac = Pack.UInt32_To_LE(authAcc);
  446. Array.Copy(mac, 0, output, outOff, mac.Length);
  447. Reset(false);
  448. return mac.Length;
  449. #endif
  450. }
  451. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  452. public int DoFinal(Span<byte> output)
  453. {
  454. if (!aadFinished)
  455. {
  456. DoProcessAADBytes(aadData.GetBuffer(), 0, (int)aadData.Length);
  457. aadFinished = true;
  458. }
  459. Accumulate();
  460. this.mac = Pack.UInt32_To_LE(authAcc);
  461. mac.CopyTo(output);
  462. Reset(false);
  463. return mac.Length;
  464. }
  465. #endif
  466. public byte[] GetMac()
  467. {
  468. return mac;
  469. }
  470. public int GetUpdateOutputSize(int len)
  471. {
  472. return len;
  473. }
  474. public int GetOutputSize(int len)
  475. {
  476. return len + 8;
  477. }
  478. private static int LenLength(int v)
  479. {
  480. if ((v & 0xff) == v)
  481. return 1;
  482. if ((v & 0xffff) == v)
  483. return 2;
  484. if ((v & 0xffffff) == v)
  485. return 3;
  486. return 4;
  487. }
  488. }
  489. }
  490. #pragma warning restore
  491. #endif