1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00
Files
wolfssl/wrapper/CSharp/wolfCrypt-FIPS-Test/KnownAnswerTests.cs
2026-10-02 09:32:25 -06:00

213 lines
12 KiB
C#

/* KnownAnswerTests.cs
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace wolfSSL.CSharp.Fips.Test
{
/* Embedded known answers. The module CASTs test the module; these test the
* wrapper's marshalling, entry point and parameter mapping for each
* symmetric service: published vectors (FIPS 180-4 / 202 "abc",
* RFC 4231, SP 800-38A F.1-F.5, RFC 4493, GCM test case 2, RFC 3610,
* CAVS Hash_DRBG) plus .NET cross-checks where .NET has the primitive. */
internal static class KnownAnswerTests
{
/* SP 800-38A F.1-F.5: AES-128 key and the first two plaintext blocks */
private static readonly byte[] Key38A = T.Hex("2b7e151628aed2a6abf7158809cf4f3c");
private static readonly byte[] Pt38A = T.Hex("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51");
private static readonly byte[] Iv38A = T.Hex("000102030405060708090a0b0c0d0e0f");
public static void Run()
{
T.Section("Embedded known answers");
T.Run("SHA-1/2/3 of \"abc\" (FIPS 180-4, FIPS 202)", () =>
{
byte[] abc = Encoding.ASCII.GetBytes("abc");
var expected = new (FipsHashType, string)[] {
(FipsHashType.Sha1, "a9993e364706816aba3e25717850c26c9cd0d89d"),
(FipsHashType.Sha224, "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"),
(FipsHashType.Sha256, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"),
(FipsHashType.Sha384, "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" +
"8086072ba1e7cc2358baeca134c825a7"),
(FipsHashType.Sha512, "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"),
(FipsHashType.Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"),
(FipsHashType.Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"),
(FipsHashType.Sha3_384, "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b2" +
"98d88cea927ac7f539f1edf228376d25"),
(FipsHashType.Sha3_512, "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e" +
"10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"),
};
foreach (var (type, hex) in expected)
{
T.Bytes(T.Hex(hex), FipsHash.Compute(type, abc), type.ToString());
}
});
T.Run("HMAC (RFC 4231 test case 1) and .NET cross-check", () =>
{
byte[] key = Enumerable.Repeat((byte)0x0b, 20).ToArray();
byte[] msg = Encoding.ASCII.GetBytes("Hi There");
var expected = new (FipsHashType, string)[] {
(FipsHashType.Sha1, "b617318655057264e28bc0b6fb378c8ef146be00"),
(FipsHashType.Sha224, "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"),
(FipsHashType.Sha256, "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"),
(FipsHashType.Sha384, "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c" +
"faea9ea9076ede7f4af152e8b2fa9cb6"),
(FipsHashType.Sha512, "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde" +
"daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"),
(FipsHashType.Sha3_256, "ba85192310dffa96e2a3a40e69774351140bb7185e1202cdcc917589f95e16bb"),
};
foreach (var (type, hex) in expected)
{
T.Bytes(T.Hex(hex), FipsHmac.Compute(type, key, msg), "HMAC-" + type);
}
byte[] k32 = Enumerable.Range(1, 32).Select(i => (byte)i).ToArray();
byte[] data = Enumerable.Range(0, 300).Select(i => (byte)(i * 7)).ToArray();
T.Bytes(HMACSHA256.HashData(k32, data), FipsHmac.Compute(FipsHashType.Sha256, k32, data), ".NET HMAC-SHA-256");
T.Bytes(HMACSHA512.HashData(k32, data), FipsHmac.Compute(FipsHashType.Sha512, k32, data), ".NET HMAC-SHA-512");
});
T.Run("AES-128 ECB/CBC/OFB/CTR (SP 800-38A F.1-F.5), both directions", () =>
{
var cases = new (string Mode, byte[] Ct, Func<bool, FipsAes> Make)[] {
("ECB", T.Hex("3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf"),
enc => FipsAes.CreateEcb(Key38A, enc)),
("CBC", T.Hex("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2"),
enc => FipsAes.CreateCbc(Key38A, Iv38A, enc)),
("OFB", T.Hex("3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed825"),
enc => FipsAes.CreateOfb(Key38A, Iv38A, enc)),
("CTR", T.Hex("874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff"),
_ => FipsAes.CreateCtr(Key38A, T.Hex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"))),
};
foreach (var (mode, ct, make) in cases)
{
using (var e = make(true))
{
T.Bytes(ct, e.Transform(Pt38A), mode + " encrypt");
}
using (var d = make(false))
{
T.Bytes(Pt38A, d.Transform(ct), mode + " decrypt");
}
}
/* .NET cross-check with an independent key, IV and length */
byte[] key = Enumerable.Range(0, 32).Select(i => (byte)(i * 3 + 1)).ToArray();
byte[] iv = Enumerable.Range(0, 16).Select(i => (byte)(255 - i)).ToArray();
byte[] pt = Enumerable.Range(0, 96).Select(i => (byte)(i * 11)).ToArray();
using var net = Aes.Create();
net.Key = key;
using var cbc = FipsAes.CreateCbc(key, iv, true);
T.Bytes(net.EncryptCbc(pt, iv, PaddingMode.None), cbc.Transform(pt), ".NET AES-256-CBC");
using var ecb = FipsAes.CreateEcb(key, true);
T.Bytes(net.EncryptEcb(pt, PaddingMode.None), ecb.Transform(pt), ".NET AES-256-ECB");
});
T.Run("CMAC-AES-128 (RFC 4493 example 2)", () =>
{
T.Bytes(T.Hex("070a16b46b4d4144f79bdd9dd04a287c"),
FipsCmac.Compute(Key38A, Pt38A.Take(16).ToArray()), "tag");
T.Bytes(T.Hex("070a16b46b4d4144"), FipsCmac.Compute(Key38A, Pt38A.Take(16).ToArray(), 8),
"8-byte tag is the leftmost 64 bits");
});
T.Run("AES-GCM (test case 2, external IV) and .NET cross-check", () =>
{
using var gcm = new FipsAesGcm(new byte[16]);
var r = gcm.EncryptWithIV(new byte[12], new byte[16]);
T.Bytes(T.Hex("0388dace60b6a392f328c2b971b2fe78"), r.Ciphertext, "ciphertext");
T.Bytes(T.Hex("ab6e47d42cec13bdf53a67b21257bddf"), r.Tag, "tag");
T.Bytes(new byte[16], gcm.Decrypt(r.IV, r.Ciphertext, r.Tag), "decrypt");
if (!AesGcm.IsSupported)
{
Console.WriteLine(" .NET AesGcm not supported on this platform; cross-check skipped");
return;
}
byte[] key = Enumerable.Range(0, 32).Select(i => (byte)(i + 5)).ToArray();
byte[] iv = Enumerable.Range(0, 12).Select(i => (byte)(i * 9)).ToArray();
byte[] pt = Enumerable.Range(0, 45).Select(i => (byte)(i ^ 0x5a)).ToArray();
byte[] aad = { 1, 2, 3, 4, 5 };
byte[] nct = new byte[pt.Length], ntag = new byte[16];
using (var n = new AesGcm(key, 16))
{
n.Encrypt(iv, pt, nct, ntag, aad);
}
using var g2 = new FipsAesGcm(key);
var r2 = g2.EncryptWithIV(iv, pt, aad);
T.Bytes(nct, r2.Ciphertext, ".NET ciphertext");
T.Bytes(ntag, r2.Tag, ".NET tag");
T.Bytes(pt, g2.Decrypt(iv, nct, ntag, aad), "decrypt .NET output");
});
T.Run("AES-CCM (RFC 3610 packet vector 1) and .NET cross-check", () =>
{
byte[] key = T.Hex("c0c1c2c3c4c5c6c7c8c9cacbcccdcecf");
byte[] nonce = T.Hex("00000003020100a0a1a2a3a4a5");
byte[] aad = T.Hex("0001020304050607");
byte[] pt = T.Hex("08090a0b0c0d0e0f101112131415161718191a1b1c1d1e");
using var ccm = new FipsAesCcm(key);
ccm.SetNonce(nonce);
var r = ccm.Encrypt(pt, aad, 8);
T.Bytes(T.Hex("588c979a61c663d2f066d0c2c0f989806d5f6b61dac384"), r.Ciphertext, "ciphertext");
T.Bytes(T.Hex("17e8d12cfdf926e0"), r.Tag, "tag");
T.Bytes(pt, ccm.Decrypt(nonce, r.Ciphertext, r.Tag, aad, 8), "decrypt");
if (!AesCcm.IsSupported)
{
Console.WriteLine(" .NET AesCcm not supported on this platform; cross-check skipped");
return;
}
byte[] k2 = Enumerable.Range(0, 16).Select(i => (byte)(i * 13)).ToArray();
byte[] n2 = Enumerable.Range(0, 12).Select(i => (byte)(i + 100)).ToArray();
byte[] p2 = Enumerable.Range(0, 40).Select(i => (byte)i).ToArray();
byte[] nct = new byte[p2.Length], ntag = new byte[16];
using (var n = new AesCcm(k2))
{
n.Encrypt(n2, p2, nct, ntag, aad);
}
using var c2 = new FipsAesCcm(k2);
c2.SetNonce(n2);
var r2 = c2.Encrypt(p2, aad);
T.Bytes(nct, r2.Ciphertext, ".NET ciphertext");
T.Bytes(ntag, r2.Tag, ".NET tag");
});
T.Run("Hash_DRBG SHA-256 (CAVS, no reseed) via the health-test service", () =>
{
byte[] entropyNonce = T.Hex("a65ad0f345db4e0effe875c3a2e71f42c7129d620ff5c119a9ef55f05185e0fb" +
"8581f9317517276e06e9607ddbcbcc2e");
byte[] expected = T.Hex("d3e160c35b99f340b2628264d1751060e0045da383ff57a57d73a673d2b8d80d" +
"aaf6a6c35a91bb4579d73fd0c8fed111b0391306828adfed528f018121b3febd" +
"c343e797b87dbb63db1333ded9d1ece177cfa6b71fe8ab1da46624ed6415e51c" +
"cde2c7ca86e283990eeaeb91120415528b2295910281b02dd431f4c9f70427df");
T.Bytes(expected, FipsRng.HealthTest(false, entropyNonce, null, expected.Length), "output");
});
}
}
}