diff options
author | NingSun <ning.sun@intel.com> | 2018-02-08 08:34:03 -0800 |
---|---|---|
committer | NingSun <ning.sun@intel.com> | 2018-02-08 09:14:52 -0800 |
commit | 0c89b3ccba7c9b7332ab67ae1936aff51ca62367 (patch) | |
tree | 70c1b1d160d4c6d0a83395ca9a87c1264d0d3439 /SoftHSMv2/src/lib/crypto/test | |
parent | 945613b4db4e07f75d2bc7463db580ddfaa700fd (diff) |
Initial sshsm project structure
Issue-ID: AAF-94
Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4
Signed-off-by: NingSun <ning.sun@intel.com>
Diffstat (limited to 'SoftHSMv2/src/lib/crypto/test')
31 files changed, 6977 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/crypto/test/AESTests.cpp b/SoftHSMv2/src/lib/crypto/test/AESTests.cpp new file mode 100644 index 0000000..008560f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/AESTests.cpp @@ -0,0 +1,1182 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + AESTests.cpp + + Contains test cases to test the AES implementation + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "AESTests.h" +#include "CryptoFactory.h" +#include "AESKey.h" +#include <stdio.h> + +CPPUNIT_TEST_SUITE_REGISTRATION(AESTests); + +void AESTests::setUp() +{ + aes = NULL; + + aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES); + + // Check the return value + CPPUNIT_ASSERT(aes != NULL); +} + +void AESTests::tearDown() +{ + if (aes != NULL) + { + CryptoFactory::i()->recycleSymmetricAlgorithm(aes); + } + + fflush(stdout); +} + +void AESTests::testBlockSize() +{ + CPPUNIT_ASSERT(aes->getBlockSize() == 16); +} + +void AESTests::testCBC() +{ + char testKeys128[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "89436760984679018453504364534464", + "49587346983643545706904580436731" + }; + + char testKeys192[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101213141516171819", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "096874395874290867409857496743857632098479834634", + "439867439058743095864395348375043296845094854983" + }; + + char testKeys256[][65] = + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20", + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F", + "4394398576098257436095746985679043867498572406874967416846341641", + "4369006859867098670492857409386741095643756930847023587048579014" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "6CAEC72F5E101C66550215ACAB6B874C62E7BD074C0A09A8EE4562EFCB4E560A3E90FA0F50391087824FC27F57618E5C", + "E20E3123AC64FCA5536E0A2DC48DBEBCECB3F260EFF4A0EB99D72F57EF38DED336EB9DD0B968D24C91E63974E7445A21", + "C7910B1634DB493998608875A4652B20C64202ED507D9DBA06F62EB20A63C32FB6C9669D42A0AC29D773E6D40A63A2AC" + }, + { + "8F48A65BF638FEDB7E6F59BAC8C110FEBA933F106D564119B88569E758B7FB83", + "125E1D93DC2C43A6FAFC508DB6F9A4A9F390D102C2300F0A3617CE95027BFAA3", + "FACB8DEF1B476400DE9796D5058E9086ECF04C927F5C160161C7A34D8288EB3C" + }, + { + "C810E96482F109C9A05D2B1BEBAC7966BB7784F58A5478C1A07EC0DB39F6D87B", + "2385391BB8F2DD97280B1FAEFACB6B5C4FE12A2274D6B967509CF18500A640D6", + "47549520EADA1A5D931EACCC922F88BA2E386089BF97C790FD2CD38553334AE4" + }, + { + "A7D9EAE80224624188CAA7012140E946", + "6ECD5C71ECA4AB9C3B71E91721CA2043", + "2F77AA438E9259F268985668B00650E5" + } + }, + { + { + "FCB2FB6BF8ED8910F023A934EB9DA550E4D5B469D75B9390F4A207E54F29412450E52E980862DC80B89F6D1D10B68AA5", + "7EF0F65513CFE3E0D21305E2ECCBB3554B0DE119720C5A86337E57F74795BC23ED9CB82A951DE3D00D7A0DC8997319DD", + "5B83BFDB6EF3AEA5191F2EE3366EDE10480E9459C0DE2994DD9C6408A377DFFF8121A38CFD1AA864559B9A435A3BDD6D" + }, + { + "81D667193D42BF19C456F4A1F7070C047D94C7EE8136FA315F938162FDDA20C1", + "2EFBA2B689C0F775097F98B569A1F20004F1A75F0C53473969DBE586ABCAE04D", + "447326913AA4565951D987F59B48870DD9285EEFCF64B429C2220E4F3E0D9DE2" + }, + { + "891DF30BAEA2D24408A9C788D59DBAC7A6F34311813216311E18E9ED7122DB1A", + "F1629B62ECDF3CDAA3DA0EBB31EE37691AF4EB2B6F9CF04A9861935B2C167D02", + "C7BD348D5E6696CB8BA813B96EA5C42C5C3C3629D18FC9DAF1B50A0AE4843C5B" + }, + { + "91C44D109D46C8E8656793680D43BE94", + "E68D8E49A19F155B7ED7253120B0D117", + "FAED8666F695C85283ECF51C96DB41CE" + } + }, + { + { + "0CCFB49FE2B7E93A556E56B2C616885FBB0515F55A4210FE2F492A4775F078655CB21691CA6A54819C2D885954809D00", + "2FC6C785D683FC35304DD161A21FA1B256F9FBB2817F1F3BEBCE7C1E292EC6999641AA6953C0FAB6DFC2942CABD32DFB", + "31FAF4E3DA19D2372666AC635FFE361E33AD7865AEF616273D8F3B471F77A0998C6A41497168A65F621D912C54A4AF28" + }, + { + "0B3842152A6365ED14AD952ABBBAF0EED2E8F36250DD25DDA301490FDE05219B", + "696BF21A887A04E194DCC18719E1BD623D8BD25A0CEF5EC2E21312ACE6C81F40", + "A2C8E61471EC80FE39AC0D8F720FEA8F2D23D04596A751C755E51CD357BCA5E0" + }, + { + "5E0EA3AFBE191A16854C7960F087958F577EA4F80160F521A12D2211FAC25E16", + "F5475B4FD48F969123C9F7FB08C7E902CCA282F167BBAFF1A7C7EDDB7BCBAC76", + "380CB860EC6DEF4F9329F4BE826DE1FE61A71629DD978F00BEFB349ACBD0BAD8" + }, + { + "BA1452E755E6A43E43B10DD2C1530093", + "07CA52926D4E8F2F6055E6E0251CB9E5", + "AB99E5FEE195B4433667AD3074A9322E" + } + }, + { + { + "D2D46E577723B30E6B5FC96DC18B2C55E0EACCB07CE07C7F30FD113A987E2A2059AB7DF8985C1AE525EFAD9CE111893C", + "CC5B220688AC0231DBC03C8886C0D0109840B9E58FBB1A6B6C261ED9E7979E951818033A25778FF328786D1777790078", + "4B4A0B3D6D4E770BECC574BF66CD401942DC4D0DCD0EC65F99B2925B688BB217FCB5C946BE986C440C93279F4670CD43" + }, + { + "29C76D62D3C4F7FECCBFD7A73B06E2ECA7AA3B2D4BE79EC945B0B88C813264D8", + "B898DCE11F3D6BB2182208E0BBBA7F404FE415D4D6D0772960E7CE3549B9899C", + "11E9552009836B51F241E972D680A9F397260163D9D5369BFC1B136FB4206966" + }, + { + "539FC6EDAE21EDDC1CC4650367F527467916A6990E540146238AA9CD6B3B4ADE", + "2D9DE2BC47DAFCF7867134110C541EBCD72D67B1B23DEF6805DBFF4A4D90EF91", + "BF484690835FF61C4A7873A996EEB91F553978A40360E192273D3923E04DFE1E" + }, + { + "4910EFFFBF571C98D51802F04A42213E", + "EDD1880FC4D41293BC74B98AF3D8A010", + "F8BCC258A6CD7FAA4EDF16A3CF5573C4" + } + }, + { + { + "C2061BD0B4274B5CB4E408B492991F4195FDBFCDED1BC57442151B182BA6E8075AAF858F357C262E0034B9B5F839D823", + "6EEFEBCC9F8C607D21A158E23980EFA6EC234DC6EA668A446F467F4AE87521F18DC1800D87A5EBC63C444F810557B61D", + "00C952BA54614A1F11B0D59F3F469A859F62CCE0D35073B91B461302A7F37BD0B23401482DFCEE66ABD12C05615C9862" + }, + { + "B36553D93EEF04AE247DBCBDDB8C039FFAC8AC1B0EF14C2E4BA653F089924451", + "90670C9DE58F95431591FA2BE8EA1B4B3F5BDBFC0B5199F94A41E4FC7B6B1645", + "A065415413D3A08E4B42A3F2681B8D122167A1E3F92D38C305761D9BF80131F1" + }, + { + "12A758F161543F2842138B8C2453C3A05A90BE9F92CB3DD10C40AB9D1D746B49", + "DF1F4DDFFE1032C812FC6F35AB2B3A7B0E8D26DA49DEC8F5E08D108DB1283BEA", + "FDCB66159E1B5CF1BE9F7271EF2C35D5E9F7485E32D16C6AC865E64619DB8724" + }, + { + "1FC224DCB64848B5E8F9FB91C542991F", + "1F8C5F65F9205098B47E26894B9154D9", + "19763CAC206EDFDEBEDAD9C274DEE1C1" + } + } + }; + + char testIV[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "69836472094875029486750948672066", + "48670943876904867104398574908554" + }; + + for (int i = 0; i < 5; i++) + { + ByteString keyData128(testKeys128[i]); + ByteString keyData192(testKeys192[i]); + ByteString keyData256(testKeys256[i]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + + // Test 128-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void AESTests::testECB() +{ + char testKeys128[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "89436760984679018453504364534464", + "49587346983643545706904580436731" + }; + + char testKeys192[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101213141516171819", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "096874395874290867409857496743857632098479834634", + "439867439058743095864395348375043296845094854983" + }; + + char testKeys256[][65] = + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20", + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F", + "4394398576098257436095746985679043867498572406874967416846341641", + "4369006859867098670492857409386741095643756930847023587048579014" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "6CAEC72F5E101C66550215ACAB6B874CD26479922B98D9839D7DA729B557ABA00143DB63EE66B0CDFF9F69917680151E", + "E20E3123AC64FCA5536E0A2DC48DBEBC0E4E53BDA45FFC97C677951A891A6B7502BB292527E726FD51EB29894D6F0AAD", + "C7910B1634DB493998608875A4652B205750B3B761DA7718E120C23A575F7D821F788FE6D86C317549697FBF0C07FA43" + }, + { + "8F48A65BF638FEDB7E6F59BAC8C110FE0E5E6370CBEFACFA0D7A5744030A481B", + "125E1D93DC2C43A6FAFC508DB6F9A4A933738D14C219340D5F4D7203DEDCA7E1", + "FACB8DEF1B476400DE9796D5058E90863A9A8C8BB2420B9A85BA3E8F87BB48F2" + }, + { + "C810E96482F109C9A05D2B1BEBAC79660143DB63EE66B0CDFF9F69917680151E", + "2385391BB8F2DD97280B1FAEFACB6B5C02BB292527E726FD51EB29894D6F0AAD", + "47549520EADA1A5D931EACCC922F88BA1F788FE6D86C317549697FBF0C07FA43" + }, + { + "A7D9EAE80224624188CAA7012140E946", + "6ECD5C71ECA4AB9C3B71E91721CA2043", + "2F77AA438E9259F268985668B00650E5" + } + }, + { + { + "8947CE273536C8A4D1E878F38371B9A8D2B3B45496779386CBA32CA70001D6AA6CC00A66D2AD83FFD76E9A2BCAD89A01", + "B151340CFECADA3AE176637D0A78686E2063E1A602C85D03AE648BDF4FA57C36F7F1878D088644BD5FB43D3C0FE1C30C", + "C19AE024C8F6B8E3383F675DF463512E273AAD7D0B88F22D5225EF09D2E37118D45D7C5AA26BCA9D6B1D5DDBF68F9EF6" + }, + { + "16C30BBAE7CDB2EE1E02275B79A064F6EE69FB37C8E039400435782F550CF86A", + "F6C869D28D2D167C50BEE8F605D33021CB9173567B8B4AB3EEC68F0298324B78", + "07DB563F7E31F1E670A02F97E8D120C7EE3FCEBBF2FDC2D37FC17D93ED1A778B" + }, + { + "52902B599686234833C4D420A9BF17FF6CC00A66D2AD83FFD76E9A2BCAD89A01", + "B17FA9EA89D5578A844B3D82891330B1F7F1878D088644BD5FB43D3C0FE1C30C", + "74BC55BE85291E0D1FA4A4444051CF65D45D7C5AA26BCA9D6B1D5DDBF68F9EF6" + }, + { + "3F00CAAC6FA432A7C1826CA4DA7C55D6", + "9C2DBF449FF2C4AC1CFD7C43D200D33A", + "E2183AB600A986806D86ADA4EE38E562" + } + }, + { + { + "23741EF993CBA04E5C67B42A16CA4D100BA6DF745E6D90818500DEC1CFC9811DBD3ACBFC853ED5DE825266C3B1883EC4", + "F14D0EB7DFDB9B8960B0E47D7F4828E8756C38BA83655AAC466986ECB229A66FA390265A4BF5F50A8DFFAD253701E418", + "0AAE579A796C94AF4FFB9D7C71381CB5E68E15465F30D7085A72D0CCEC7030BBC9CB7B3859E1A550BCBF11B624022C56" + }, + { + "AFCD6801459845C88548CC337BDD4D8B87E81D9D6AC945E14E3C4E0AC976A4B9", + "117129A4775FC84E703F2F2C54B1B55DC4A79241F6CB0A37A8D551D71983D944", + "1128250DA7C9A1BBE6A61AC01F28D4D9E3027C3625BD5514AE5DFE4B9132DAFA" + }, + { + "B275BDAF14AE286643C533258343F822BD3ACBFC853ED5DE825266C3B1883EC4", + "93ACFCCFE2C4736B6492A673A59DACE2A390265A4BF5F50A8DFFAD253701E418", + "2C2165E6491662A855FD7A20CDFF23BDC9CB7B3859E1A550BCBF11B624022C56" + }, + { + "30BBF52D760BAEA653FD03E5E84E583A", + "F5F55DF3FC4D9CF2A2829BACA774A51A", + "7EE196D148C11FA4998A90C6C7932395" + } + }, + { + { + "44C2B3344B002BB7A6994E1C74CC7BA70CE55BF44FD96506B553F0EFD3FE02B28329D59D480B0C1714A0DC60EB9FA8CE", + "568C7627FD2519BE6031F052DE8F680860F7680460E92A524EA912174BE17B1337D593DEF15FB5BA64F03D1AAE276775", + "99E36C0097BCFE41945C064EFA476FF4AA6048F909BEDE32A649F1035A2FB83CD601D09C3FDB36BC61B8CDE5BDD73804" + }, + { + "D748E8E93D29775BD8831E3BC1E1ABF75F484C7CC693521A66A5AB1637822E40", + "010103778E123E5140F8D0356DA831E1587DB7E416AE9FAD14C6E2F78DC83148", + "A8B8926E8FB762A1AB8CD9FA08507D77872C8EAAAFF3527572F49497B8B366C9" + }, + { + "CFF3212C7E94C2DD65EC1CDC998D6C4B8329D59D480B0C1714A0DC60EB9FA8CE", + "324D16FEEC9DCA75A80F4B80175F8A7537D593DEF15FB5BA64F03D1AAE276775", + "850567F4F0200CFBF88F1A6D35CAF6D9D601D09C3FDB36BC61B8CDE5BDD73804" + }, + { + "417F142D7609AE701B3D263FFECE4502", + "E0DC994D8DC01C4EB2ECD19AD120C3D1", + "FB26CC4E48B40EAB755FF65164EFB406" + } + }, + { + { + "048AEE75741BC60D01B512A53FEE97238F294743E7A351FAF589DD9E040BB8AF0F59D8F60E9C700F10025B5E69828819", + "67FB10E52640B1E060F3D7868524721AC375DC76628B0D79C5F40ADC653FC001B50C33356548289D3E70EB7FBC0E2B56", + "31953FF249D7519D3C39FB21D70A41033286A320193CC938C5ACBBCA2B25340829799212E3CABACE0BFD4424427705AB" + }, + { + "8D8D50FA4619F0E1B821DCA4ACBDFD46AE92D76A0B95A0331D61C4A7032D9705", + "10685E8F632AC41D92E3A0403BB20C79868BD6F94691226EC54D7220C45E7233", + "C5FF99FD1BC2BFDBEA62894B279DE6CBF51CCD00362A557DB9D9102DAF623A50" + }, + { + "0330B8FF58E4E6E956B4F81F7A4770200F59D8F60E9C700F10025B5E69828819", + "C79BABE5B34B305B05E38013DC5568F7B50C33356548289D3E70EB7FBC0E2B56", + "98BEE460FF803288C898A900DD08CE2529799212E3CABACE0BFD4424427705AB" + }, + { + "9A4FD3A26DD0D3A12F224E5E7A06EB76", + "B86FE6F088C3A6497F21BCB29DB703D1", + "313CC604B301DACA48CDB6F405AA7938" + } + } + }; + + char testIV[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "69836472094875029486750948672066", + "48670943876904867104398574908554" + }; + + for (int i = 0; i < 5; i++) + { + ByteString keyData128(testKeys128[i]); + ByteString keyData192(testKeys192[i]); + ByteString keyData256(testKeys256[i]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + + // Test 128-bit key + + // Get the reference for the encrypted data + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void AESTests::testCTR() +{ + // Test vectors from RFC3686 + + char testKeys128[][33] = + { + "AE6852F8121067CC4BF7A5765577F39E", + "7E24067817FAE0D743D6CE1F32539163", + "7691BE035E5020A8AC6E618529F9A0DC" + }; + + char testKeys192[][49] = + { + "16AF5B145FC9F579C175F93E3BFB0EED863D06CCFDB78515", + "7C5CB2401B3DC33C19E7340819E0F69C678C3DB8E6F6A91A", + "02BF391EE8ECB159B959617B0965279BF59B60A786D3E0FE" + }; + + char testKeys256[][65] = + { + "776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104", + "F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884", + "FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D" + }; + + char testData[][256] = + { + "53696E676C6520626C6F636B206D7367", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223" + }; + + char testResult[3][3][256] = + { + { + "E4095D4FB7A7B3792D6175A3261311B8", + "4B55384FE259C9C84E7935A003CBE928", + "145AD01DBF824EC7560863DC71E3E0C0" + }, + { + "5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28", + "453243FC609B23327EDFAAFA7131CD9F8490701C5AD4A79CFC1FE0FF42F4FB00", + "F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C" + }, + { + "C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F", + "96893FC55E5C722F540B7DD1DDF7E758D288BC95C69165884536C811662F2188ABEE0935", + "EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8" + } + }; + + char testCB[3][3][33] = + { + { + "00000030000000000000000000000001", + "0000004836733C147D6D93CB00000001", + "00000060DB5672C97AA8F0B200000001" + }, + { + "006CB6DBC0543B59DA48D90B00000001", + "0096B03B020C6EADC2CB500D00000001", + "00FAAC24C1585EF15A43D87500000001" + }, + { + "00E0017B27777F3F4A1786F000000001", + "0007BDFD5CBD60278DCC091200000001", + "001CC5B751A51D70A1C1114800000001" + } + }; + + for (int i = 0; i < 3; i++) + { + ByteString keyData128(testKeys128[i]); + ByteString keyData192(testKeys192[i]); + ByteString keyData256(testKeys256[i]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + + ByteString plainText(testData[i]), shsmPlainText; + ByteString CB; + ByteString cipherText; + ByteString shsmCipherText, OB; + + // Test 128-bit key + CB = ByteString(testCB[i][0]); + cipherText = ByteString(testResult[i][0]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + CB = ByteString(testCB[i][1]); + cipherText = ByteString(testResult[i][1]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + CB = ByteString(testCB[i][2]); + cipherText = ByteString(testResult[i][2]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } +} + +#ifdef WITH_AES_GCM +void AESTests::testGCM() +{ + // Test vectors from NIST via Botan + + char test128[8][6][256] = + { + { + "00000000000000000000000000000000", + "000000000000000000000000", + "", + "", + "10", + "58E2FCCEFA7E3061367F1D57A4E7455A" + }, + { + "00000000000000000000000000000000", + "000000000000000000000000", + "00000000000000000000000000000000", + "", + "10", + "0388DACE60B6A392F328C2B971B2FE78AB6E47D42CEC13BDF53A67B21257BDDF" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBADDECAF888", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B391AAFD255", + "", + "10", + "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E091473F59854D5C2AF327CD64A62CF35ABD2BA6FAB4" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBADDECAF888", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "10", + "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E0915BC94FBC3221A5DB94FAE95AE7121A47" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBAD", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "10", + "61353B4C2806934A777FF51FA22A4755699B2A714FCDC6F83766E5F97B6C742373806900E49F24B22B097544D4896B424989B5E1EBAC0F07C23F45983612D2E79E3B0785561BE14AACA2FCCB" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "9313225DF88406E555909C5AFF5269AA6A7A9538534F7DA1E4C303D2A318A728C3C0C95156809539FCF0E2429A6B525416AEDBF5A0DE6A57A637B39B", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "10", + "8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C1699D050" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBAD", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "C", + "61353B4C2806934A777FF51FA22A4755699B2A714FCDC6F83766E5F97B6C742373806900E49F24B22B097544D4896B424989B5E1EBAC0F07C23F45983612D2E79E3B0785561BE14A" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "9313225DF88406E555909C5AFF5269AA6A7A9538534F7DA1E4C303D2A318A728C3C0C95156809539FCF0E2429A6B525416AEDBF5A0DE6A57A637B39B", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "C", + "8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C" + } + }; + + char test192[8][6][256] = + { + { + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "", + "", + "10", + "cd33b28ac773f74ba00ed1f312572435" + }, + { + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "00000000000000000000000000000000", + "", + "10", + "98e7247c07f0fe411c267e4384b0f6002ff58d80033927ab8ef4d4587514f0fb" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "", + "10", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade2569924a7c8587336bfb118024db8674a14" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd6d27618c" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca40d3533f8" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373bdcf566ff291c25bbb8568fc3d376a6d9" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca4" + } + }; + + char test256[8][6][256] = + { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "", + "", + "10", + "530f8afbc74536b9a963b4f1c4cb738b" + }, + { + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "00000000000000000000000000000000", + "", + "10", + "cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "", + "10", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015adb094dac5d93471bdec1a502270e3cc6c" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb2d551b" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913fe2ea8f2", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3fa44a8266ee1c8eb0c8b5d4cf5ae9f19a" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913" + } + }; + + for (int i = 0; i < 8; i++) + { + ByteString keyData128(test128[i][0]); + ByteString keyData192(test192[i][0]); + ByteString keyData256(test256[i][0]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + ByteString IV; + ByteString plainText; + ByteString AAD; + size_t tagBits; + ByteString cipherText; + + ByteString shsmPlainText; + ByteString shsmCipherText; + ByteString OB; + + // Test 128-bit key + IV = ByteString(test128[i][1]); + plainText = ByteString(test128[i][2]); + AAD = ByteString(test128[i][3]); + tagBits = ByteString(test128[i][4]).long_val(); + cipherText = ByteString(test128[i][5]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + CPPUNIT_ASSERT(OB.size() == 0); + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + IV = ByteString(test192[i][1]); + plainText = ByteString(test192[i][2]); + AAD = ByteString(test192[i][3]); + tagBits = ByteString(test192[i][4]).long_val(); + cipherText = ByteString(test192[i][5]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + CPPUNIT_ASSERT(OB.size() == 0); + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + IV = ByteString(test256[i][1]); + plainText = ByteString(test256[i][2]); + AAD = ByteString(test256[i][3]); + tagBits = ByteString(test256[i][4]).long_val(); + cipherText = ByteString(test256[i][5]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + CPPUNIT_ASSERT(OB.size() == 0); + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } +} +#endif + +void AESTests::testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode) +{ + for (int i = 0; i < testCnt; i++) + { + ByteString kekData(testKeK[i]); + ByteString keyData(testKey[i]); + + AESKey aesKeK(kekData.size() * 8); + CPPUNIT_ASSERT(aesKeK.setKeyBits(kekData)); + + ByteString wrapped; + ByteString expectedCt(testCt[i]); + CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, mode, keyData, wrapped)); + CPPUNIT_ASSERT(wrapped.size() == expectedCt.size()); + CPPUNIT_ASSERT(wrapped == expectedCt); + + ByteString unwrapped; + CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, mode, wrapped, unwrapped)); + CPPUNIT_ASSERT(unwrapped.size() == keyData.size()); + CPPUNIT_ASSERT(unwrapped == keyData); +/* + #ifdef HAVE_AES_KEY_WRAP_PAD + keyData.resize(20); + ByteString padwrapped; + CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, keyData, padwrapped)); + CPPUNIT_ASSERT(padwrapped.size() == 32); + + ByteString padunwrapped; + CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, padwrapped, padunwrapped)); + CPPUNIT_ASSERT(padunwrapped == keyData); + #endif +*/ + } +} + +// RFC 3394 tests +void AESTests::testWrapWoPad() +{ + char testKeK[][128] = { + "000102030405060708090A0B0C0D0E0F", // section 4.1 + "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.2 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.3 + "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.4 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.5 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.6 + }; + char testKey[][128] = { + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F" + }; + char testCt[][128] = { + "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5", + "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D", + "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7", + "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2", + "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1", + "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21" + }; + + testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP); +} + +// RFC 5649 tests +void AESTests::testWrapPad() +{ + char testKeK[][128] = { + "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 1 + "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 2 + }; + char testKey[][128] = { + "C37B7E6492584340BED12207808941155068F738", + "466F7250617369" + }; + char testCt[][128] = { + "138BDEAA9B8FA7FC61F97742E72248EE5AE6AE5360D1AE6A5F54F373FA543B6A", + "AFBEB0F07DFBF5419200F2CCB50BB24F" + }; + + testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP_PAD); +} diff --git a/SoftHSMv2/src/lib/crypto/test/AESTests.h b/SoftHSMv2/src/lib/crypto/test/AESTests.h new file mode 100644 index 0000000..3a50b11 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/AESTests.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + AESTests.h + + Contains test cases to test the AES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_AESTESTS_H +#define _SOFTHSM_V2_AESTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "SymmetricAlgorithm.h" + +class AESTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(AESTests); + CPPUNIT_TEST(testBlockSize); + CPPUNIT_TEST(testCBC); + CPPUNIT_TEST(testECB); + CPPUNIT_TEST(testCTR); +#ifdef WITH_AES_GCM + CPPUNIT_TEST(testGCM); +#endif +#ifdef HAVE_AES_KEY_WRAP + CPPUNIT_TEST(testWrapWoPad); +#endif +#ifdef HAVE_AES_KEY_WRAP_PAD + CPPUNIT_TEST(testWrapPad); +#endif + CPPUNIT_TEST_SUITE_END(); + +public: + void testBlockSize(); + void testCBC(); + void testECB(); + void testCTR(); +#ifdef WITH_AES_GCM + void testGCM(); +#endif + void testWrapWoPad(); + void testWrapPad(); + + void setUp(); + void tearDown(); + +private: + // AES instance + SymmetricAlgorithm* aes; + void testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode); +}; + +#endif // !_SOFTHSM_V2_AESTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/DESTests.cpp b/SoftHSMv2/src/lib/crypto/test/DESTests.cpp new file mode 100644 index 0000000..bcb1c6b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DESTests.cpp @@ -0,0 +1,1164 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + DESTests.cpp + + Contains test cases to test the DES implementation + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "DESTests.h" +#include "CryptoFactory.h" +#include "DESKey.h" +#include <stdio.h> + +CPPUNIT_TEST_SUITE_REGISTRATION(DESTests); + +void DESTests::setUp() +{ + des = NULL; + + des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES); + + // Check the return value + CPPUNIT_ASSERT(des != NULL); +} + +void DESTests::tearDown() +{ + if (des != NULL) + { + CryptoFactory::i()->recycleSymmetricAlgorithm(des); + } + + fflush(stdout); +} + +void DESTests::testBlockSize() +{ + CPPUNIT_ASSERT(des->getBlockSize() == 8); +} + +void DESTests::testCBC() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7", + "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7", + "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7" + }, + { + "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64", + "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64", + "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64" + }, + { + "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588", + "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588", + "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588" + }, + { + "B81DA29972385E55CB453A17B6D88D22", + "B81DA29972385E55CB453A17B6D88D22", + "B81DA29972385E55CB453A17B6D88D22" + } + }, + { + { + "EE16FFE3CC4D4589766FA0957FB728A75D44A00D9BEBE2D43C4D4F3A5AFDB49730CFD4DF46D3AEF6", + "A070EE9DED89EE198E0E9B3CEB4879BB0244AB7FCD3450ED044BB5EE0AC8F7797383FDB8AAEF77B8", + "E7C594590C9CA00B376B702CE3B92C3F699B3EEEB2CEA08FA551350C837BF031FCAF4E1E97450327" + }, + { + "D4142C47C700069F3E71EA6B1EF301B9B97261543ED75B32242C05A253B077B8", + "102BBE7D93CD0EF66280D3FA1F2A3976FB9C4D1B155D19E4985ADB86015DDE8C", + "600C3A75AC6EB4C4609BA6B7ED273ED56E59CD49FC911C33DD8DFCA384BAA462" + }, + { + "47452120CD84CC32FC72F3B8600E5C43EEE192A29BC6BCB7", + "ADCF4292A32E51A7843CC8590E6934083A2CC847082FF2B4", + "D0FA596AC00BDA870999FD3FA2494C3C8B40B261EB3066F6" + }, + { + "6BD20CDBE6E6ECAD6ED829FB43E92751", + "AE4379E371E295F63423F861B59111F0", + "2757FC58EDEEB8499EA9B49AB2729BAD" + } + }, + { + { + "298621D5237F6230067DE7871DDBA6991E85CA14AD661D21357240923604D23A6A4119277B75B331", + "2C9F4FC0ACE7C8A4847472A0D5DDD42F36D3B2C46144B5A0ECDBB59806472E6257952DFD4DB9EBE5", + "679A832C630207E76BC1FF8371C61CA2518E37FE97EDED1B171E3E11807250145736949368AC822B" + }, + { + "80FFD37B545675BB8C7CD317A73AB48CC0A39D3D9C11474EC3FD1220A066C034", + "F9228036718792EE86A85626AB1BC05E17F9CE21FF5D1723D0442CE852F004C3", + "D5F5F1EA7D8C2038FEDCBEDF157A5D2469A941FEC696D74DB8359CA5AECDD4CE" + }, + { + "1ABB1CC10F589D993030A978B1B7F44AD52FFFEBF23638CA", + "D2423F54FA4978C95E4B13EF4DD6AA82DFD772F0FDAF5AD1", + "8128EC49D71F5711E5304E7C4423C63AD0EFC45453B66583" + }, + { + "B9EE976AB97396047510C1DEA5C86A4B", + "46BA1930042146B31BD8FAF3AE6F3414", + "46EF3BCCA73E33C03D81BFE0DFFA7ABD" + } + }, + { + { + "30D1B2556D516F20C2FD117FE0355845FBB0B11ABE5922A7EAA19C3A48E30207218321B3F0F30A6D", + "CBFA560297901DD691CDFDF98675BD7FF3A64FDCC0EF02F29C81105D3ECAC4E2803E2279F4476B35", + "4A30EC10433BE3695DC2B064E6240419C7BF81F1EE7640D5E2FFFA106666A2CEBF18DB954A992B5E" + }, + { + "61FFB2E5A73170603E48F9823E6DF7105C9A909CC2F5CEDBEA7E60C076355B37", + "8408BD722B12031D17A1645AA59B05E2A50F7002B19877D6EB1C9BB7107C523F", + "97EF5791017B10CF07FB8144C19633522CBBE55DC63EF608F8734EE6484C0B0E" + }, + { + "7205DC463B3D5EC858C8E7A13844A1A8FF21C0D615CA56AF", + "D5D08C1DC728A47CD55A2ACBB811294962022E745F4BCDF4", + "7761189D73039A3F06BDDF00B308D7A43BE7BEA1CE9D042E" + }, + { + "1702428661BA4CFE686CFDEDFFAA6A27", + "9218A89B0A7AEC7E6E2AF1CA493B2829", + "6EEB9F7DDF66CED3DB74F7E8DE0CB2CD" + } + }, + { + { + "4FD3A4C759827F6E188E542B83A858026C17FD1DEF21477A964D122B62EE55FA9DB3CCF05A768C83", + "F2C8B52652970805EE60ECECC8369C98443463F1C3A5A6357DFDFEE6B7F1EF0CF05523B5469E4555", + "21FCBDC92C07F112D19742F5100F2A995E27CB282D73DF5CFEC802C629A279BD4E498C98D170003E" + }, + { + "3FD4C32A44DC0A9605A5A793C57E94826E80FC9E8E9620BBC2E02FE41A62A2D3", + "4FC88F1E88C3B5A76CF6BE5FA8205BA6F7FA201F7C40E8F0F9CA156E140A4EC5", + "CCE31260C967F4B9BB3D2D31F82320715E434C1313D911C58CE7E42AA78DA831" + }, + { + "714766BE5CB60DA99DC0BD4E7E655ADE7F26E45F372EF1BF", + "00064542E2B4821B4E9173DA6FD1ABAE45C5E5CF26DB506D", + "4D88D531C20E63A39372F275329BDBEBE15E7D2C32F2A98F" + }, + { + "4933917C9B56124914D2B76DE221BA13", + "7F2D1CA9D942630FE1E954E4176E84A5", + "9A46902F3997F0EB121981DAEC6D89C4" + } + } + }; + + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void DESTests::testECB() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0", + "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0", + "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0" + }, + { + "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0", + "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0", + "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0" + }, + { + "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0", + "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0", + "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0" + }, + { + "B81DA29972385E55EA1F3677CDC02D27", + "B81DA29972385E55EA1F3677CDC02D27", + "B81DA29972385E55EA1F3677CDC02D27" + } + }, + { + { + "278B2CA6259C30E180CCB62E69F0841F235507E2FB3404FC2BC223E37E32B3A78207EA5D3E19A5FD", + "417579E3ABEF6F0D620B4FF88E2220457466420803140BFEFBA062A2A41D7C15061019377C6BFD8A", + "A676D0404F0F105B2073B9DD19C8C434428098BFC5AF1292FE12477340395F118F45B5BE23F16C4E" + }, + { + "7D004390E5638E54077E2551B01BD52BFA1B98403ECE1AEF8207EA5D3E19A5FD", + "391B84593FEA836450318A6E943F1C3A4A6BD74E5001EB7A061019377C6BFD8A", + "DEAF58111ECCCB449F0C2564B52E360E4AACC8672ABBDF1A8F45B5BE23F16C4E" + }, + { + "A6947F9EF4159BAE636A70B904059BC38207EA5D3E19A5FD", + "14ADFE212E27BF7F409395B45577F2C8061019377C6BFD8A", + "FF87BF761FC159F4442B3B4593233BC48F45B5BE23F16C4E" + }, + { + "3A1777DAAAC85389EE0B499A90AE1739", + "376E61DF2EAFE5B523964A03885AD085", + "E4D81EE64FE8FB187EB7B5E80E075C73" + } + }, + { + { + "F105809DF621715F4D3492E1EEC4A7DE0775A0632ECC13429DF0DC695A60882FA47F93E855A1445B", + "77C85215179312315997B4D0E997DB413176C80A8ED9F5EB9B726200224CE97C20A8A19F543BCCBD", + "AF1477E32B5BB1CA46D26B6020B3B48DB0A90A97B1BA60F032ADA648296EC92DEE924AA617423FD1" + }, + { + "0FB3C3D9D93E0025F87909CD351D0116C0F684A204015E2CA47F93E855A1445B", + "67A66DB3209C406D2FE31AF6C36D24C7B32D0F8F1EAFA90020A8A19F543BCCBD", + "F85B1F07D788C59CD3DE6D562A175725DF596847ADEA8764EE924AA617423FD1" + }, + { + "243A34CD70CE3819B9510980B6EFF3EAA47F93E855A1445B", + "997E145467B88D9D4C923797F539AC1620A8A19F543BCCBD", + "836788D7AD1F879B405438775FFD6D76EE924AA617423FD1" + }, + { + "70856D6B67EE353F27EBB96462DACE63", + "D02F2A92C175A58001D89C4AEC476384", + "4ED379A40187826CAA90D2D6A05D5A9B" + } + }, + { + { + "C79F67ABCE6F741CF6D5B7B4870397779AEB89F48805DD1A28305E804A4A2B91114E1CF0C7FA91DA", + "42956EA3B9415E8FE75B667A7C6B1ADF64D08E53C38DE733A776A97C7A8FC27E32945078552FA3E2", + "3685365AD0F07609E13CCDE69CEDC8CCA0C37262A87B734286B9119643AC3BABE435BDA25919BE86" + }, + { + "09B882774309CC2B117586F5FA8BF7E4A5DA2A65E137665B114E1CF0C7FA91DA", + "0E52A9ABE753758D3C4F6326A8F689282D1DAB8AF6FC8CFF32945078552FA3E2", + "8DB6B9D50B5B8CE7DA56546CFF36C16BA3159E0EB7BD649AE435BDA25919BE86" + }, + { + "025F9704F6ACD844BCFC6EBA809CD871114E1CF0C7FA91DA", + "1692C6A1DF9192C6D4125991EA9A9CBE32945078552FA3E2", + "6B848E67225EDDCCD7E8EC89ACDAA0AFE435BDA25919BE86" + }, + { + "9D01CD89916AEE48AFE528A376E07AE9", + "6FA6A689405048060D65E1B1240B76B7", + "7EADEB7073D2EA995C5ED613C978817F" + } + }, + { + { + "A98D0E8E72C589D80D240F192CF65C30FF3A1AB9D8CE54B09AA249C72E395AC3B40F19A649C1B237", + "33AC43C7A936665859431D18C089EE45F1356C34F5DF462D81BBFA42380A7E4F6732A473091A3673", + "FD4F2F77CCE20147CD0932B2E2D8D5978523F6A03D59E31E1F678A5DA4C350132E94F199555C371E" + }, + { + "39453F3BF3C0CAE54279D96F4592359A5AEE6DD04D5F6162B40F19A649C1B237", + "E2AFCEEFF2317C520D890D7F2CB91ACD99D5DCAEC9C409016732A473091A3673", + "CB19BF88B2DEDDE981E048379A47BDF77ED5F815034CB07A2E94F199555C371E" + }, + { + "9D466BACFA69266F7CC26D2C8B8CD203B40F19A649C1B237", + "265FDBCCF5F2325B3C8770ABEEECA4166732A473091A3673", + "C61E9B86A8A663AE1566CFFCF2046D6B2E94F199555C371E" + }, + { + "380091B24160152B63EF067F6C189385", + "548EB237B455CBA0100A5C52A6F28C2B", + "066C3B0C5E6AF1E9BDD3DDAE5040F809" + } + } + }; + + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void DESTests::testOFB() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846", + "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846", + "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846" + }, + { + "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F", + "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F", + "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F" + }, + { + "E89FCA8099D6B1FF6795867965624526", + "E89FCA8099D6B1FF6795867965624526", + "E89FCA8099D6B1FF6795867965624526" + }, + { + "CA253BAC45D205E236", + "CA253BAC45D205E236", + "CA253BAC45D205E236" + } + }, + { + { + "3E9FB188FC11138D05109EA396CA48E1681DF27A857C3C4A9E92D3DC85A5F313", + "3440BEFCF35DC87716D8440F71BAF9ACD0441E10B9E5B525F0584499620086E2", + "DDB35281888DF064195C42D45E4E2571AD62113A228B5107D1AC849861C199C0" + }, + { + "233FC5D8B6F005B02500727078E84ED16C1B0474D7277E45", + "29E0CAACB9BCDE4A36C8A8DC9F98FF9CD442E81EEBBEF72A", + "C01326D1C26CE659394CAE07B06C2341A964E73470D01308" + }, + { + "139E51D5AD1EF0E10AC3809975FF4DFE", + "19415EA1A2522B1B190B5A35928FFCB3", + "F0B2B2DCD9821308168F5CEEBD7B206E" + }, + { + "3124A0F9711A44FC5B", + "3BFBAF8D7E569F0648", + "D20843F00586A71547" + } + }, + { + { + "E376288A10BD52CB7162ADA9A732D24B574B1E7CB4FF5C791FFEA2E481AD3049", + "FD82CFAE85B8581FFCF489F467D94B1B4FAAAEDDE4EC531ABD30D7EA235896AA", + "24D9411BA456571900244AEA3EA7159BAA96522B6F891606A8D9A559FE218A9B" + }, + { + "FED65CDA5A5C44F65172417A4910D47B534DE872E6A41E76", + "E022BBFECF594E22DCE4652789FB4D2B4BAC58D3B6B71115", + "3979354BEEB741242034A639D08513ABAE90A4253DD25409" + }, + { + "CE77C8D741B2B1A77EB1B3934407D754", + "D0832FF3D4B7BB73F32797CE84EC4E04", + "09D8A146F559B4750FF754D0DD921084" + }, + { + "ECCD39FB9DB605BA2F", + "F239DEDF08B30F6EA2", + "2B62506A295D00685E" + } + }, + { + { + "740A4786C73A7C6B52DAF270161895E13B4437C56B9837827C2FE237532F4C19", + "581B63C58404AEBECFDFD51D74A79836C11514685B47F3B02A2419AF0AA8C625", + "D5FCB196868673D136D480E0B6EFC33C589131D87A4AC004A6E0DE8ADC8DE611" + }, + { + "69AA33D68DDB6A5672CA1EA3F83A93D13F42C1CB39C3758D", + "45BB1795CEE5B883EFCF39CE9A859E06C513E266091CB1BF", + "C85CC5C6CC6765EC16C46C3358CDC50C5C97C7D62811820B" + }, + { + "590BA7DB96359F075D09EC4AF52D90FE", + "751A8398D50B4DD2C00CCB2797929D29", + "F8FD51CBD78990BD39079EDA55DAC623" + }, + { + "7BB156F74A312B1A0C", + "57A072B4090FF9CF91", + "DA47A0E70B8D24A068" + } + }, + { + { + "0855A84EAD2176C3F10B9DCFC8D1A379AF616FC5C5CD4E6D434353C52832F9F6", + "A8420E97462B0215AAC1DB0835D4064C6A8B123327FC396C9520BEA70B59B412", + "3461DEDF1B4893E16706900E1DDBE351E90C1300B9B01E8A518A01AD56E9AC8C" + }, + { + "15F5DC1EE7C060FED11B711C26F3A549AB6799CB97960C62", + "B5E27AC70CCA14288AD137DBDBF6007C6E8DE43D75A77B63", + "29C1AA8F51A985DC47167CDDF3F9E561ED0AE50EEBEB5C85" + }, + { + "25544813FC2E95AFFED883F52BE4A666", + "8543EECA1724E179A512C532D6E10353", + "19603E824A47708D68D58E34FEEEE64E" + }, + { + "07EEB93F202A21B2AF", + "A7F91FE6CB205564F4", + "3BDACFAE9643C49039" + } + } + }; + + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void DESTests::testCFB() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F", + "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F", + "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F" + }, + { + "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B", + "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B", + "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B" + }, + { + "E89FCA8099D6B1FFB3A24C435B847A73", + "E89FCA8099D6B1FFB3A24C435B847A73", + "E89FCA8099D6B1FFB3A24C435B847A73" + }, + { + "CA253BAC45D205E270", + "CA253BAC45D205E270", + "CA253BAC45D205E270" + } + }, + { + { + "3E9FB188FC11138D49C438ABB98A3846671A4DB257AA62C7929CD55A43E46D88", + "3440BEFCF35DC8773DD631A9C8CCF222009D45E301BBF6432A78E99416CE87D8", + "DDB35281888DF06446772085E3DE849298B4BE0089979260DDC59FACB17AD0BE" + }, + { + "233FC5D8B6F005B0966FB313EA0DDFBECF19CBC937445A56", + "29E0CAACB9BCDE4AB219A19AA77E2C9A407C98A18BD56FDF", + "C01326D1C26CE6592FA4E9909D93A85BE005431046661C73" + }, + { + "139E51D5AD1EF0E1E74DD9919AE65DB6", + "19415EA1A2522B1B5972F5DCBEEF4E01", + "F0B2B2DCD9821308815ADB01F0A16B76" + }, + { + "3124A0F9711A44FC92", + "3BFBAF8D7E569F06CF", + "D20843F00586A715DB" + } + }, + { + { + "E376288A10BD52CB06B42B4582A425907D2DF490EC14B478507BCDE58CE95B02", + "FD82CFAE85B8581F1409EB62D06A98E05C401607619DE1235822E2DEB74737E1", + "24D9411BA4565719BE9FF1A4D91F23B3BF8980A706747077583C8EB84AF63745" + }, + { + "FED65CDA5A5C44F619325429C78F464D271807342B10F899", + "E022BBFECF594E22ABC22FA25024B6FD8F61337CBD1F023D", + "3979354BEEB741241F0D219B5521A488F870C849275FF8B9" + }, + { + "CE77C8D741B2B1A7E488B94EB32C96FD", + "D0832FF3D4B7BB73AEC7646A3686ABCF", + "09D8A146F559B475A6258D03BC6F8BD3" + }, + { + "ECCD39FB9DB605BAB2", + "F239DEDF08B30F6EE4", + "2B62506A295D00687E" + } + }, + { + { + "740A4786C73A7C6B435071A654DA8FCC75BA3299969E327A2ABC7024378CF3AA", + "581B63C58404AEBE49FA5FA4032918813075279E836DFE9BAEDF37D9B21ABEE1", + "D5FCB196868673D1FA9C8A67E6A2449354B292E1A76BA11C416A394116857B29" + }, + { + "69AA33D68DDB6A561FB6D6218FAC0E812514782FC6059E46", + "45BB1795CEE5B883232EBCCB672FC9C4803C6B827825FE94", + "C85CC5C6CC6765EC466B8F8AC8DFC91CB916F617873AF187" + }, + { + "590BA7DB96359F07DB2F2CE68748425C", + "751A8398D50B4DD24E4681B6D0E880FC", + "F8FD51CBD78990BD5D088ECA798DA0E6" + }, + { + "7BB156F74A312B1A8C", + "57A072B4090FF9CF1B", + "DA47A0E70B8D24A043" + } + }, + { + { + "0855A84EAD2176C3D2C3DE4FB868CA2C1B0DF550E187E29808C45594C070FBF4", + "A8420E97462B02158D2CABD1574D072F8D83123CED9BA7CEDD7C2799E168F32D", + "3461DEDF1B4893E182BE36017DEBC6669B15269DFA4435A31EB1A0CE6A845176" + }, + { + "15F5DC1EE7C060FEDC9B1B43A20588E7A073A300BEFC4CAD", + "B5E27AC70CCA142857CB807226DC1EA9B31BE81C0FDCD3FB", + "29C1AA8F51A985DC7E530E6EB7AEAC246F2ED097D09851CC" + }, + { + "25544813FC2E95AF817E0897D4E22ECD", + "8543EECA1724E179543979F02103C150", + "19603E824A47708D80E29D3A61BAE5EA" + }, + { + "07EEB93F202A21B250", + "A7F91FE6CB205564F2", + "3BDACFAE9643C49027" + } + } + }; + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/test/DESTests.h b/SoftHSMv2/src/lib/crypto/test/DESTests.h new file mode 100644 index 0000000..0834462 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DESTests.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + DESTests.h + + Contains test cases to test the DES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DESTESTS_H +#define _SOFTHSM_V2_DESTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "SymmetricAlgorithm.h" + +class DESTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DESTests); + CPPUNIT_TEST(testBlockSize); + CPPUNIT_TEST(testCBC); + CPPUNIT_TEST(testECB); + CPPUNIT_TEST(testOFB); + CPPUNIT_TEST(testCFB); + CPPUNIT_TEST_SUITE_END(); + +public: + void testBlockSize(); + void testCBC(); + void testECB(); + void testOFB(); + void testCFB(); + + void setUp(); + void tearDown(); + +private: + // DES instance + SymmetricAlgorithm* des; +}; + +#endif // !_SOFTHSM_V2_DESTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/DHTests.cpp b/SoftHSMv2/src/lib/crypto/test/DHTests.cpp new file mode 100644 index 0000000..354cdac --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DHTests.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + DHTests.cpp + + Contains test cases to test the DH class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "DHTests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#include "DHParameters.h" +#include "DHPublicKey.h" +#include "DHPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(DHTests); + +void DHTests::setUp() +{ + dh = NULL; + + dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH); + + // Check the DH object + CPPUNIT_ASSERT(dh != NULL); +} + +void DHTests::tearDown() +{ + if (dh != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(dh); + } + + fflush(stdout); +} + +void DHTests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + DHParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dh->generateParameters(ap, (void*) *k)); + + // Generate key-pair + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p)); + + DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey(); + DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getBitLength() == *k); + CPPUNIT_ASSERT(priv->getBitLength() == *k); + + dh->recycleKeyPair(kp); + + // Generate key-pair with a fixed private value length + p->setXBitLength(128); + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p)); + + priv = (DHPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(priv->getX().bits() == 128); + + dh->recycleParameters(p); + dh->recycleKeyPair(kp); + } +} + +void DHTests::testSerialisation() +{ + // Generate 1024-bit parameters for testing + DHParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dh->generateParameters(ap, (void*) 1024)); + + // Set a fixed private value length + p->setXBitLength(128); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dP; + + CPPUNIT_ASSERT(dh->reconstructParameters(&dP, serialisedParams)); + + CPPUNIT_ASSERT(dP->areOfType(DHParameters::type)); + + DHParameters* ddP = (DHParameters*) dP; + + CPPUNIT_ASSERT(p->getP() == ddP->getP()); + CPPUNIT_ASSERT(p->getG() == ddP->getG()); + CPPUNIT_ASSERT(p->getXBitLength() == ddP->getXBitLength()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, dP)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(dh->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + DHPrivateKey* privKey = (DHPrivateKey*) kp->getPrivateKey(); + DHPublicKey* pubKey = (DHPublicKey*) kp->getPublicKey(); + + DHPrivateKey* dPrivKey = (DHPrivateKey*) dKP->getPrivateKey(); + DHPublicKey* dPubKey = (DHPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP()); + CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG()); + CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX()); + + CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP()); + CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG()); + CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY()); + + dh->recycleParameters(p); + dh->recycleParameters(dP); + dh->recycleKeyPair(kp); + dh->recycleKeyPair(dKP); +} + +void DHTests::testPKCS8() +{ + // Generate 1024-bit parameters for testing + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dh->generateParameters(&p, (void*) 1024)); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + DHPrivateKey* dPriv = (DHPrivateKey*) dh->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getG() == dPriv->getG()); + CPPUNIT_ASSERT(priv->getX() == dPriv->getX()); + + dh->recycleParameters(p); + dh->recycleKeyPair(kp); + dh->recyclePrivateKey(dPriv); +} + +void DHTests::testDerivation() +{ + AsymmetricKeyPair* kpa; + AsymmetricKeyPair* kpb; + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dh->generateParameters(&p, (void*) *k)); + + // Generate key-pairs + CPPUNIT_ASSERT(dh->generateKeyPair(&kpa, p)); + CPPUNIT_ASSERT(dh->generateKeyPair(&kpb, p)); + + // Derive secrets + SymmetricKey* sa; + CPPUNIT_ASSERT(dh->deriveKey(&sa, kpb->getPublicKey(), kpa->getPrivateKey())); + SymmetricKey* sb; + CPPUNIT_ASSERT(dh->deriveKey(&sb, kpa->getPublicKey(), kpb->getPrivateKey())); + + // Must be the same + CPPUNIT_ASSERT(sa->getKeyBits() == sb->getKeyBits()); + + // Clean up + dh->recycleSymmetricKey(sa); + dh->recycleSymmetricKey(sb); + dh->recycleKeyPair(kpa); + dh->recycleKeyPair(kpb); + dh->recycleParameters(p); + } +} + +void DHTests::testDeriveKnownVector() +{ + // TODO +} + diff --git a/SoftHSMv2/src/lib/crypto/test/DHTests.h b/SoftHSMv2/src/lib/crypto/test/DHTests.h new file mode 100644 index 0000000..e2a58ac --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DHTests.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + DHTests.h + + Contains test cases to test the DH class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DHTESTS_H +#define _SOFTHSM_V2_DHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class DHTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DHTests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testDerivation); + CPPUNIT_TEST(testDeriveKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testDerivation(); + void testDeriveKnownVector(); + + void setUp(); + void tearDown(); + +private: + // DH instance + AsymmetricAlgorithm* dh; +}; + +#endif // !_SOFTHSM_V2_DHTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/DSATests.cpp b/SoftHSMv2/src/lib/crypto/test/DSATests.cpp new file mode 100644 index 0000000..80f2514 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DSATests.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + DSATests.cpp + + Contains test cases to test the RNG class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "DSATests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#include "DSAParameters.h" +#include "DSAPublicKey.h" +#include "DSAPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(DSATests); + +void DSATests::setUp() +{ + dsa = NULL; + + dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA); + + // Check the DSA object + CPPUNIT_ASSERT(dsa != NULL); +} + +void DSATests::tearDown() +{ + if (dsa != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa); + } + + fflush(stdout); +} + +void DSATests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Key sizes to test + std::vector<size_t> keySizes; +#ifndef WITH_FIPS + keySizes.push_back(1024); + keySizes.push_back(1536); +#else + keySizes.push_back(1024); +#endif +#ifndef WITH_BOTAN + keySizes.push_back(2048); +#endif + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + DSAParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) *k)); + + // Generate key-pair + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); + + DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey(); + DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getBitLength() == *k); + CPPUNIT_ASSERT(priv->getBitLength() == *k); + + dsa->recycleParameters(p); + dsa->recycleKeyPair(kp); + } +} + +void DSATests::testSerialisation() +{ + // Generate 1024-bit parameters for testing + DSAParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) 1024)); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dP; + + CPPUNIT_ASSERT(dsa->reconstructParameters(&dP, serialisedParams)); + + CPPUNIT_ASSERT(dP->areOfType(DSAParameters::type)); + + DSAParameters* ddP = (DSAParameters*) dP; + + CPPUNIT_ASSERT(p->getP() == ddP->getP()); + CPPUNIT_ASSERT(p->getQ() == ddP->getQ()); + CPPUNIT_ASSERT(p->getG() == ddP->getG()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, dP)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(dsa->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + DSAPrivateKey* privKey = (DSAPrivateKey*) kp->getPrivateKey(); + DSAPublicKey* pubKey = (DSAPublicKey*) kp->getPublicKey(); + + DSAPrivateKey* dPrivKey = (DSAPrivateKey*) dKP->getPrivateKey(); + DSAPublicKey* dPubKey = (DSAPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP()); + CPPUNIT_ASSERT(privKey->getQ() == dPrivKey->getQ()); + CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG()); + CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX()); + + CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG()); + CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY()); + + dsa->recycleParameters(p); + dsa->recycleParameters(dP); + dsa->recycleKeyPair(kp); + dsa->recycleKeyPair(dKP); +} + +void DSATests::testPKCS8() +{ + // Generate 1024-bit parameters for testing + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) 1024)); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + DSAPrivateKey* dPriv = (DSAPrivateKey*) dsa->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ()); + CPPUNIT_ASSERT(priv->getG() == dPriv->getG()); + CPPUNIT_ASSERT(priv->getX() == dPriv->getX()); + + dsa->recycleParameters(p); + dsa->recycleKeyPair(kp); + dsa->recyclePrivateKey(dPriv); +} + +void DSATests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + + // Key sizes to test + std::vector<size_t> keySizes; +#ifndef WITH_FIPS + keySizes.push_back(1024); + keySizes.push_back(1536); +#else + keySizes.push_back(1024); +#endif +#ifndef WITH_BOTAN + keySizes.push_back(2048); +#endif + + // Mechanisms to test + std::vector<AsymMech::Type> mechanisms; + mechanisms.push_back(AsymMech::DSA_SHA1); + mechanisms.push_back(AsymMech::DSA_SHA224); + mechanisms.push_back(AsymMech::DSA_SHA256); + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) *k)); + + // Generate key-pair + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); + + // Generate some data to sign + ByteString dataToSign; + + RNG* rng = CryptoFactory::i()->getRNG(); + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); + + // Test mechanisms that perform internal hashing + for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++) + { + ByteString blockSignature, singlePartSignature; + + // Sign the data in blocks + CPPUNIT_ASSERT(dsa->signInit(kp->getPrivateKey(), *m)); + CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(0, 134))); + CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134, 289))); + CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134 + 289))); + CPPUNIT_ASSERT(dsa->signFinal(blockSignature)); + + // Sign the data in one pass + CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m)); + + // Now perform multi-pass verification + CPPUNIT_ASSERT(dsa->verifyInit(kp->getPublicKey(), *m)); + CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(0, 125))); + CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125, 247))); + CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125 + 247))); + CPPUNIT_ASSERT(dsa->verifyFinal(blockSignature)); + + // And single-pass verification + CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m)); + } + + // Test mechanisms that do not perform internal hashing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, *k >= 2048 ? 32 : 20)); + + // Sign the data + ByteString signature; + CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::DSA)); + + // Verify the signature + CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::DSA)); + + dsa->recycleKeyPair(kp); + dsa->recycleParameters(p); + } +} + +void DSATests::testSignVerifyKnownVector() +{ + DSAPublicKey* pubKey1 = (DSAPublicKey*) dsa->newPublicKey(); + DSAPublicKey* pubKey2 = (DSAPublicKey*) dsa->newPublicKey(); + DSAPrivateKey* privKey1 = (DSAPrivateKey*) dsa->newPrivateKey(); + DSAPrivateKey* privKey2 = (DSAPrivateKey*) dsa->newPrivateKey(); + + // Reconstruct public and private key #1 + ByteString p1 = "e0a67598cd1b763bc98c8abb333e5dda0cd3aa0e5e1fb5ba8a7b4eabc10ba338fae06dd4b90fda70d7cf0cb0c638be3341bec0af8a7330a3307ded2299a0ee606df035177a239c34a912c202aa5f83b9c4a7cf0235b5316bfc6efb9a248411258b30b839af172440f32563056cb67a861158ddd90e6a894c72a5bbef9e286c6b"; + ByteString q1 = "e950511eab424b9a19a2aeb4e159b7844c589c4f"; + ByteString g1 = "d29d5121b0423c2769ab21843e5a3240ff19cacc792264e3bb6be4f78edd1b15c4dff7f1d905431f0ab16790e1f773b5ce01c804e509066a9919f5195f4abc58189fd9ff987389cb5bedf21b4dab4f8b76a055ffe2770988fe2ec2de11ad92219f0b351869ac24da3d7ba87011a701ce8ee7bfe49486ed4527b7186ca4610a75"; + ByteString x1 = "d0ec4e50bb290a42e9e355c73d8809345de2e139"; + ByteString y1 = "25282217f5730501dd8dba3edfcf349aaffec20921128d70fac44110332201bba3f10986140cbb97c726938060473c8ec97b4731db004293b5e730363609df9780f8d883d8c4d41ded6a2f1e1bbbdc979e1b9d6d3c940301f4e978d65b19041fcf1e8b518f5c0576c770fe5a7a485d8329ee2914a2de1b5da4a6128ceab70f79"; + + pubKey1->setP(p1); + pubKey1->setQ(q1); + pubKey1->setG(g1); + pubKey1->setY(y1); + privKey1->setP(p1); + privKey1->setQ(q1); + privKey1->setG(g1); + privKey1->setX(x1); + + // Test with key #1 + ByteString data1 = "616263"; // "abc" + ByteString goodSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347704"; + ByteString badSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347705"; + + // Reconstruct public and private key #2 + ByteString p2 = "f56c2a7d366e3ebdeaa1891fd2a0d099436438a673fed4d75f594959cffebca7be0fc72e4fe67d91d801cba0693ac4ed9e411b41d19e2fd1699c4390ad27d94c69c0b143f1dc88932cfe2310c886412047bd9b1c7a67f8a25909132627f51a0c866877e672e555342bdf9355347dbd43b47156b2c20bad9d2b071bc2fdcf9757f75c168c5d9fc43131be162a0756d1bdec2ca0eb0e3b018a8b38d3ef2487782aeb9fbf99d8b30499c55e4f61e5c7dcee2a2bb55bd7f75fcdf00e48f2e8356bdb59d86114028f67b8e07b127744778aff1cf1399a4d679d92fde7d941c5c85c5d7bff91ba69f9489d531d1ebfa727cfda651390f8021719fa9f7216ceb177bd75"; + ByteString q2 = "c24ed361870b61e0d367f008f99f8a1f75525889c89db1b673c45af5867cb467"; + ByteString g2 = "8dc6cc814cae4a1c05a3e186a6fe27eaba8cdb133fdce14a963a92e809790cba096eaa26140550c129fa2b98c16e84236aa33bf919cd6f587e048c52666576db6e925c6cbe9b9ec5c16020f9a44c9f1c8f7a8e611c1f6ec2513ea6aa0b8d0f72fed73ca37df240db57bbb27431d618697b9e771b0b301d5df05955425061a30dc6d33bb6d2a32bd0a75a0a71d2184f506372abf84a56aeeea8eb693bf29a640345fa1298a16e85421b2208d00068a5a42915f82cf0b858c8fa39d43d704b6927e0b2f916304e86fb6a1b487f07d8139e428bb096c6d67a76ec0b8d4ef274b8a2cf556d279ad267ccef5af477afed029f485b5597739f5d0240f67c2d948a6279"; + ByteString x2 = "0caf2ef547ec49c4f3a6fe6df4223a174d01f2c115d49a6f73437c29a2a8458c"; + ByteString y2 = "2828003d7c747199143c370fdd07a2861524514acc57f63f80c38c2087c6b795b62de1c224bf8d1d1424e60ce3f5ae3f76c754a2464af292286d873a7a30b7eacbbc75aafde7191d9157598cdb0b60e0c5aa3f6ebe425500c611957dbf5ed35490714a42811fdcdeb19af2ab30beadff2907931cee7f3b55532cffaeb371f84f01347630eb227a419b1f3f558bc8a509d64a765d8987d493b007c4412c297caf41566e26faee475137ec781a0dc088a26c8804a98c23140e7c936281864b99571ee95c416aa38ceebb41fdbff1eb1d1dc97b63ce1355257627c8b0fd840ddb20ed35be92f08c49aea5613957d7e5c7a6d5a5834b4cb069e0831753ecf65ba02b"; + + pubKey2->setP(p2); + pubKey2->setQ(q2); + pubKey2->setG(g2); + pubKey2->setY(y2); + privKey2->setP(p2); + privKey2->setQ(q2); + privKey2->setG(g2); + privKey2->setX(x2); + + // Test with key #2 + ByteString data2 = "616263"; // "abc" + ByteString goodSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb9"; + ByteString badSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb8"; + + CPPUNIT_ASSERT(dsa->verify(pubKey1, data1, goodSignature1, AsymMech::DSA_SHA1)); + CPPUNIT_ASSERT(!dsa->verify(pubKey1, data1, badSignature1, AsymMech::DSA_SHA1)); + CPPUNIT_ASSERT(dsa->verify(pubKey2, data2, goodSignature2, AsymMech::DSA_SHA256)); + CPPUNIT_ASSERT(!dsa->verify(pubKey2, data2, badSignature2, AsymMech::DSA_SHA256)); + + dsa->recyclePublicKey(pubKey1); + dsa->recyclePublicKey(pubKey2); + dsa->recyclePrivateKey(privKey1); + dsa->recyclePrivateKey(privKey2); +} diff --git a/SoftHSMv2/src/lib/crypto/test/DSATests.h b/SoftHSMv2/src/lib/crypto/test/DSATests.h new file mode 100644 index 0000000..446733a --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DSATests.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + DSATests.h + + Contains test cases to test the DSA class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DSATESTS_H +#define _SOFTHSM_V2_DSATESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class DSATests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DSATests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + + void setUp(); + void tearDown(); + +private: + // DSA instance + AsymmetricAlgorithm* dsa; +}; + +#endif // !_SOFTHSM_V2_DSATESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp b/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp new file mode 100644 index 0000000..1646fd8 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + ECDHTests.cpp + + Contains test cases to test the ECDH class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "ECDHTests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#ifdef WITH_ECC +#include "ECParameters.h" +#include "ECPublicKey.h" +#include "ECPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(ECDHTests); + +void ECDHTests::setUp() +{ + ecdh = NULL; + + ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH); + + // Check the ECDH object + CPPUNIT_ASSERT(ecdh != NULL); +} + +void ECDHTests::tearDown() +{ + if (ecdh != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh); + } + + fflush(stdout); +} + +void ECDHTests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Curves to test + std::vector<ByteString> curves; + // Add X9.62 prime256v1 + curves.push_back(ByteString("06082a8648ce3d030107")); + // Add secp384r1 + curves.push_back(ByteString("06052b81040022")); + + for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++) + { + // Set domain parameters + ECParameters* p = new ECParameters; + p->setEC(*c); + + // Generate key-pair + CPPUNIT_ASSERT(ecdh->generateKeyPair(&kp, p)); + + ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey(); + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getEC() == *c); + CPPUNIT_ASSERT(priv->getEC() == *c); + + ecdh->recycleParameters(p); + ecdh->recycleKeyPair(kp); + } +} + +void ECDHTests::testSerialisation() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dEC; + + CPPUNIT_ASSERT(ecdh->reconstructParameters(&dEC, serialisedParams)); + + CPPUNIT_ASSERT(dEC->areOfType(ECParameters::type)); + + ECParameters* ddEC = (ECParameters*) dEC; + + CPPUNIT_ASSERT(p->getEC() == ddEC->getEC()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(ecdh->generateKeyPair(&kp, dEC)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(ecdh->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + ECPrivateKey* privKey = (ECPrivateKey*) kp->getPrivateKey(); + ECPublicKey* pubKey = (ECPublicKey*) kp->getPublicKey(); + + ECPrivateKey* dPrivKey = (ECPrivateKey*) dKP->getPrivateKey(); + ECPublicKey* dPubKey = (ECPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getEC() == dPrivKey->getEC()); + CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD()); + + CPPUNIT_ASSERT(pubKey->getEC() == dPubKey->getEC()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + + ecdh->recycleParameters(p); + ecdh->recycleParameters(dEC); + ecdh->recycleKeyPair(kp); + ecdh->recycleKeyPair(dKP); +} + +void ECDHTests::testPKCS8() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(ecdh->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + ECPrivateKey* dPriv = (ECPrivateKey*) ecdh->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getEC() == dPriv->getEC()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + + ecdh->recycleParameters(p); + ecdh->recycleKeyPair(kp); + ecdh->recyclePrivateKey(dPriv); +} + +void ECDHTests::testDerivation() +{ + AsymmetricKeyPair* kpa; + AsymmetricKeyPair* kpb; + ECParameters* p; + + // Curves to test + std::vector<ByteString> curves; + // Add X9.62 prime256v1 + curves.push_back(ByteString("06082a8648ce3d030107")); + // Add secp384r1 + curves.push_back(ByteString("06052b81040022")); + + for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++) + { + // Get parameters + p = new ECParameters; + CPPUNIT_ASSERT(p != NULL); + p->setEC(*c); + + // Generate key-pairs + CPPUNIT_ASSERT(ecdh->generateKeyPair(&kpa, p)); + CPPUNIT_ASSERT(ecdh->generateKeyPair(&kpb, p)); + + // Derive secrets + SymmetricKey* sa; + CPPUNIT_ASSERT(ecdh->deriveKey(&sa, kpb->getPublicKey(), kpa->getPrivateKey())); + SymmetricKey* sb; + CPPUNIT_ASSERT(ecdh->deriveKey(&sb, kpa->getPublicKey(), kpb->getPrivateKey())); + + // Must be the same + CPPUNIT_ASSERT(sa->getKeyBits() == sb->getKeyBits()); + + // Clean up + ecdh->recycleSymmetricKey(sa); + ecdh->recycleSymmetricKey(sb); + ecdh->recycleKeyPair(kpa); + ecdh->recycleKeyPair(kpb); + ecdh->recycleParameters(p); + } +} + +void ECDHTests::testDeriveKnownVector() +{ + ECPublicKey* pubKeya = (ECPublicKey*) ecdh->newPublicKey(); + ECPublicKey* pubKeyb = (ECPublicKey*) ecdh->newPublicKey(); + ECPrivateKey* privKeya = (ECPrivateKey*) ecdh->newPrivateKey(); + ECPrivateKey* privKeyb = (ECPrivateKey*) ecdh->newPrivateKey(); + + // Reconstruct public and private key for Alice + ByteString ec = "06082a8648ce3d030107"; // X9.62 prime256v1 + ByteString da = "c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433"; + // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front! + ByteString qa = "044104dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3"; + + pubKeya->setEC(ec); + pubKeya->setQ(qa); + privKeya->setEC(ec); + privKeya->setD(da); + + // Reconstruct public and private key for Bob + ByteString db = "c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0b283ab46476bee53"; + ByteString qb = "044104d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab"; + + pubKeyb->setEC(ec); + pubKeyb->setQ(qb); + privKeyb->setEC(ec); + privKeyb->setD(db); + + // Test + ByteString expected = "d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de"; + SymmetricKey* sa; + CPPUNIT_ASSERT(ecdh->deriveKey(&sa, pubKeya, privKeyb)); + CPPUNIT_ASSERT(sa->getKeyBits() == expected); + SymmetricKey* sb; + CPPUNIT_ASSERT(ecdh->deriveKey(&sb, pubKeyb, privKeya)); + CPPUNIT_ASSERT(sb->getKeyBits() == expected); + + ecdh->recyclePublicKey(pubKeya); + ecdh->recyclePublicKey(pubKeyb); + ecdh->recyclePrivateKey(privKeya); + ecdh->recyclePrivateKey(privKeyb); + ecdh->recycleSymmetricKey(sa); + ecdh->recycleSymmetricKey(sb); +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/test/ECDHTests.h b/SoftHSMv2/src/lib/crypto/test/ECDHTests.h new file mode 100644 index 0000000..81cf6d5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDHTests.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + ECDHTests.h + + Contains test cases to test the ECDH class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ECDHTESTS_H +#define _SOFTHSM_V2_ECDHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class ECDHTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ECDHTests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testDerivation); + CPPUNIT_TEST(testDeriveKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testDerivation(); + void testDeriveKnownVector(); + + void setUp(); + void tearDown(); + +private: + // ECDH instance + AsymmetricAlgorithm* ecdh; +}; + +#endif // !_SOFTHSM_V2_ECDHTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp b/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp new file mode 100644 index 0000000..3c29d06 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + ECDSATests.cpp + + Contains test cases to test the ECDSA class + *****************************************************************************/ + +#include <stdlib.h> +#include <utility> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "ECDSATests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#ifdef WITH_ECC +#include "ECParameters.h" +#include "ECPublicKey.h" +#include "ECPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(ECDSATests); + +void ECDSATests::setUp() +{ + ecdsa = NULL; + + ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA); + + // Check the ECDSA object + CPPUNIT_ASSERT(ecdsa != NULL); +} + +void ECDSATests::tearDown() +{ + if (ecdsa != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa); + } + + fflush(stdout); +} + +void ECDSATests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Curves to test + std::vector<ByteString> curves; + // Add X9.62 prime256v1 + curves.push_back(ByteString("06082a8648ce3d030107")); + // Add secp384r1 + curves.push_back(ByteString("06052b81040022")); + // Add secp521r1 + curves.push_back(ByteString("06052b81040023")); + + for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++) + { + // Set domain parameters + ECParameters* p = new ECParameters; + p->setEC(*c); + + // Generate key-pair + CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, p)); + + ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey(); + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getEC() == *c); + CPPUNIT_ASSERT(priv->getEC() == *c); + + ecdsa->recycleParameters(p); + ecdsa->recycleKeyPair(kp); + } +} + +void ECDSATests::testSerialisation() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dEC; + + CPPUNIT_ASSERT(ecdsa->reconstructParameters(&dEC, serialisedParams)); + + CPPUNIT_ASSERT(dEC->areOfType(ECParameters::type)); + + ECParameters* ddEC = (ECParameters*) dEC; + + CPPUNIT_ASSERT(p->getEC() == ddEC->getEC()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, dEC)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(ecdsa->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + ECPrivateKey* privKey = (ECPrivateKey*) kp->getPrivateKey(); + ECPublicKey* pubKey = (ECPublicKey*) kp->getPublicKey(); + + ECPrivateKey* dPrivKey = (ECPrivateKey*) dKP->getPrivateKey(); + ECPublicKey* dPubKey = (ECPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getEC() == dPrivKey->getEC()); + CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD()); + + CPPUNIT_ASSERT(pubKey->getEC() == dPubKey->getEC()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + + ecdsa->recycleParameters(p); + ecdsa->recycleParameters(dEC); + ecdsa->recycleKeyPair(kp); + ecdsa->recycleKeyPair(dKP); +} + +void ECDSATests::testPKCS8() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + ECPrivateKey* dPriv = (ECPrivateKey*) ecdsa->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getEC() == dPriv->getEC()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + + ecdsa->recycleParameters(p); + ecdsa->recycleKeyPair(kp); + ecdsa->recyclePrivateKey(dPriv); +} + +void ECDSATests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + ECParameters *p; + + // Curves/Hashes to test + std::vector<std::pair<ByteString, HashAlgo::Type> > totest; + // Add X9.62 prime256v1 + totest.push_back(std::make_pair(ByteString("06082a8648ce3d030107"), HashAlgo::SHA256)); + // Add secp384r1 + totest.push_back(std::make_pair(ByteString("06052b81040022"), HashAlgo::SHA384)); + // Add secp521r1 + totest.push_back(std::make_pair(ByteString("06052b81040023"), HashAlgo::SHA384)); + + for (std::vector<std::pair<ByteString, HashAlgo::Type> >::iterator k = totest.begin(); k != totest.end(); k++) + { + // Get parameters + p = new ECParameters; + CPPUNIT_ASSERT(p != NULL); + p->setEC(k->first); + HashAlgorithm *hash; + hash = CryptoFactory::i()->getHashAlgorithm(k->second); + CPPUNIT_ASSERT(hash != NULL); + + // Generate key-pair + CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, p)); + + // Generate some data to sign + ByteString dataToSign; + + RNG* rng = CryptoFactory::i()->getRNG(); + CPPUNIT_ASSERT(rng != NULL); + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); + + // Sign the data + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(dataToSign)); + ByteString hResult; + CPPUNIT_ASSERT(hash->hashFinal(hResult)); + ByteString sig; + CPPUNIT_ASSERT(ecdsa->sign(kp->getPrivateKey(), hResult, sig, AsymMech::ECDSA)); + + // And verify it + CPPUNIT_ASSERT(ecdsa->verify(kp->getPublicKey(), hResult, sig, AsymMech::ECDSA)); + + ecdsa->recycleKeyPair(kp); + ecdsa->recycleParameters(p); + CryptoFactory::i()->recycleHashAlgorithm(hash); + } +} + +void ECDSATests::testSignVerifyKnownVector() +{ + ECPublicKey* pubKey1 = (ECPublicKey*) ecdsa->newPublicKey(); + ECPublicKey* pubKey2 = (ECPublicKey*) ecdsa->newPublicKey(); + ECPrivateKey* privKey1 = (ECPrivateKey*) ecdsa->newPrivateKey(); + ECPrivateKey* privKey2 = (ECPrivateKey*) ecdsa->newPrivateKey(); + HashAlgorithm* hash1 = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA256); + HashAlgorithm* hash2 = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA384); + + // Reconstruct public and private key #1 + ByteString ec1 = "06082a8648ce3d030107"; // X9.62 prime256v1 + ByteString d1 = "dc51d3866a15bacde33d96f992fca99da7e6ef0934e7097559c27f1614c88a7f"; + // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front! + ByteString q1 = "0441042442a5cc0ecd015fa3ca31dc8e2bbc70bf42d60cbca20085e0822cb04235e9706fc98bd7e50211a4a27102fa3549df79ebcb4bf246b80945cddfe7d509bbfd7d"; + + pubKey1->setEC(ec1); + pubKey1->setQ(q1); + privKey1->setEC(ec1); + privKey1->setD(d1); + CPPUNIT_ASSERT(hash1 != NULL); + + // Test with key #1 + ByteString data1 = "616263"; // "abc" + ByteString goodSignature1 = "cb28e0999b9c7715fd0a80d8e47a77079716cbbf917dd72e97566ea1c066957c86fa3bb4e26cad5bf90b7f81899256ce7594bb1ea0c89212748bff3b3d5b0315"; + ByteString badSignature1 = "cb28e0999b9c7715fd0a80d8e47a77079716cbbf917dd72e97566ea1c066957c86fa3bb4e26cad5bf90b7f81899256ce7594bb1ea0c89212748bff3b3d5b0316"; + + // Reconstruct public and private key #2 + ByteString ec2 = "06052b81040022"; // secp384r1 + ByteString d2 = "0beb646634ba87735d77ae4809a0ebea865535de4c1e1dcb692e84708e81a5af62e528c38b2a81b35309668d73524d9f"; + // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front! + ByteString q2 = "04610496281bf8dd5e0525ca049c048d345d3082968d10fedf5c5aca0c64e6465a97ea5ce10c9dfec21797415710721f437922447688ba94708eb6e2e4d59f6ab6d7edff9301d249fe49c33096655f5d502fad3d383b91c5e7edaa2b714cc99d5743ca"; + + pubKey2->setEC(ec2); + pubKey2->setQ(q2); + privKey2->setEC(ec2); + privKey2->setD(d2); + CPPUNIT_ASSERT(hash2 != NULL); + + // Test with key #2 + ByteString data2 = "616263"; // "abc" + ByteString goodSignature2 = "fb017b914e29149432d8bac29a514640b46f53ddab2c69948084e2930f1c8f7e08e07c9c63f2d21a07dcb56a6af56eb3b263a1305e057f984d38726a1b46874109f417bca112674c528262a40a629af1cbb9f516ce0fa7d2ff630863a00e8b9f"; + ByteString badSignature2 = "fb017b914e29149432d8bac29a514640b46f53ddab2c69948084e2930f1c8f7e08e07c9c63f2d21a07dcb56a6af56eb3b263a1305e057f984d38726a1b46874109f417bca112674c528262a40a629af1cbb9f516ce0fa7d2ff630863a00e8b9e"; + + CPPUNIT_ASSERT(hash1->hashInit()); + CPPUNIT_ASSERT(hash1->hashUpdate(data1)); + ByteString hResult1; + CPPUNIT_ASSERT(hash1->hashFinal(hResult1)); + CPPUNIT_ASSERT(ecdsa->verify(pubKey1, hResult1, goodSignature1, AsymMech::ECDSA)); + CPPUNIT_ASSERT(!ecdsa->verify(pubKey1, hResult1, badSignature1, AsymMech::ECDSA)); + CPPUNIT_ASSERT(hash2->hashInit()); + CPPUNIT_ASSERT(hash2->hashUpdate(data2)); + ByteString hResult2; + CPPUNIT_ASSERT(hash2->hashFinal(hResult2)); + CPPUNIT_ASSERT(ecdsa->verify(pubKey2, hResult2, goodSignature2, AsymMech::ECDSA)); + CPPUNIT_ASSERT(!ecdsa->verify(pubKey2, hResult2, badSignature2, AsymMech::ECDSA)); + + ecdsa->recyclePublicKey(pubKey1); + ecdsa->recyclePublicKey(pubKey2); + ecdsa->recyclePrivateKey(privKey1); + ecdsa->recyclePrivateKey(privKey2); + CryptoFactory::i()->recycleHashAlgorithm(hash1); + CryptoFactory::i()->recycleHashAlgorithm(hash2); +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/test/ECDSATests.h b/SoftHSMv2/src/lib/crypto/test/ECDSATests.h new file mode 100644 index 0000000..70b3345 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDSATests.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + ECDSATests.h + + Contains test cases to test the ECDSA class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ECDSATESTS_H +#define _SOFTHSM_V2_ECDSATESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class ECDSATests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ECDSATests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + + void setUp(); + void tearDown(); + +private: + // ECDSA instance + AsymmetricAlgorithm* ecdsa; +}; + +#endif // !_SOFTHSM_V2_ECDSATESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp b/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp new file mode 100644 index 0000000..91f6876 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + GOSTTests.cpp + + Contains test cases to test the GOST implementations + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "GOSTTests.h" +#include "CryptoFactory.h" +#include <stdio.h> +#include "AsymmetricAlgorithm.h" +#include "AsymmetricKeyPair.h" +#include "HashAlgorithm.h" +#include "MacAlgorithm.h" +#include "RNG.h" +#ifdef WITH_GOST +#include "ECParameters.h" +#include "GOSTPublicKey.h" +#include "GOSTPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(GOSTTests); + +void GOSTTests::setUp() +{ + hash = NULL; + mac = NULL; + gost = NULL; + rng = NULL; + + gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST); + + // Check the GOST object + CPPUNIT_ASSERT(gost != NULL); +} + +void GOSTTests::tearDown() +{ + if (hash != NULL) + { + CryptoFactory::i()->recycleHashAlgorithm(hash); + } + + if (mac != NULL) + { + CryptoFactory::i()->recycleMacAlgorithm(mac); + } + + if (gost != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(gost); + } + + fflush(stdout); +} + +void GOSTTests::testHash() +{ + char testData[4096] = "FE5A773751EAB2F18921C04806D6907444557B4469CDA7C822288E5065DA58F448A27FA0B4C8786853F246B093E3DBFDC332759D7764B6D057895184D9B82E626DF70AEB99B969EA35E5BE4D50C7406EA4A7450AC063933F96F77960EE711A445593119CF69061702CB4797F214FA440C94127E3DCD92F2C71B39D354C6F4284E030DCBFCB91EA5E543E0E3560ECD355091850BA080287BD87B74BB84A8892E0F2172F136D187305179F23EB8296BF1798405BAB52E201F22BCA5B793C5BA6F2CA15F154598EEC73E7E61B405262F6FE5FDC0F9AE0528801C3F965956C79A6C6805EDD0C6515AEA27D1DB9D70A56B0F13A544429C448FB6DB390C0E367EDF997E0B681ADE3846D77D1898F06FB60CB2384015F3749BD1E8163E532529E4D3BB8B200BBE79DA76D4865621FF2E583A1A1F8EBFB7A51B65DC9152B173A7DF91C6943F2FE497CDBC306827146199ADA925DD42B8A48429F5B6E3670AA85A44BDFAB3D273EA6711B996B5C27E04949BE61ED9ECB932F429ADCF31A2E0E9F83FCB1CE6BC0EE81627D1F9D08ECD599F16A1D68B256B002E90A8B4E5830A049ECE9ADF1D50C027EC537DD5412AA1509E91CEF358B2D495D3B37651987F51D9643A5AF2E0EF3D8C02E6023BB76FF8F1EB5CD018FA32BD7886A1A46A7D5CA15E4E0CDB793F0C1986EF4480305801A518B1D4596AAA741C093FC7AD075B637B1B2CC4DA33B6EB6D549001B33E1753C9C4358FB541FDE6541238BD011CD8ACAFB4CFF15B289872956DFBCC732593E838B6300E48ED3455CD101920114640A5B7C1250E419B7D771EC65934F53176BBD7A61A36D6D3D64A1F29C3D41745993636F812930E2936E9ED34E92A3C31239176ED3F78461EE80C54D92CBD9EF9F5746F8069809A38549FC7A8FD99FB350C27230966D6001D3136114A7BDCDEE495B72E4A633845BC88400DEDADC2FA2CD8640049CDB4F8F695C45EACF24FD573E1FB1670F688C9D7706A9AE9EB30E0DFDD54C7F3F3EE6F9BBFBBED6DB6E7C7B979E677DCD8457949DC271BD6ACB445B16247D8DAC1B59D45B8FFBBFDAEA20A5C450E0F93B399AE69887E1C721B0EF86C8CD37FC7514C4F2B70AA1E757DE95DCC3B74C6E18E51D272D433330826435B7CBA6C099558B51E408B1BFE60E876141A74195A00BF914F2536D92170FB43E078D98F784E6F150ED2B16DB5B629EBABF16444639C87A544050E03FB7CCD538DA29C45CE764F68682B48BF8AE5ED43064E833338A88605B1743FEB025D5F5607BB13A2078A99924A2D4818CD582ACDC1556FAEBA70959DE8498F3FCBF85BD269A7DF23A3AD5704908978031667C7BF4A85D1EF42F3ED144670E6EEB5D8213DB43B0B7B43767FD4277EF0EC52B5718A7D187A003DE8E5DFF9C3A3CD520615FB9B52281506E5BB033818E0912980A8BCAA54E21C5630B9E863C83"; + char testResult[512] = "3EC65819A084AD30712C4B3EB69CE130A8C7221EA3D8A9996D4BA6F298BC39F9"; + + // Get a GOST R 34.11-94 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::GOST)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), gostHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(gostHash)); + + CPPUNIT_ASSERT(osslHash == gostHash); + + // Now recreate the hash in a single part operation + gostHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(gostHash)); + + CPPUNIT_ASSERT(osslHash == gostHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void GOSTTests::testHmac() +{ + char testData[4096] = "1450414E94B2CEA9E202B8ACC9C358EBA5334C20CF1B7D13E8B79BE63A0A938A340CF710D539262F406787AF7188990C7D75780C265E37750510FA6AAA742D01C753548219C20B1283CCA9D30AA5A8650D0C5EE63FE10268F9CD5996F8DB0158C6FAD147AE41C0E565F6FBC85115E17BB0B448208075D1CF79CF70574098E7116A5C5EFFDB05DCD83E71DB4860B3AEC2612FB9DE1B010229A413055724AB07F4131B04800286D3C4895A158E7B1301F8010E718C76CC69B34C643D2B1EACC00F9CD0DEBC83425256B2524B34D61EBA32FE5F79FE0A1F9360E3CFB4C88CE7CC3C36E969A37827AD5FD79BFAC08CCA1786F30F34ADC605545F04BA96CA4A4E3DF7FEC36E43406E9CD68D708CBAC4C54B2E18E38535BD1A8029FD7393B5462AB688F8146445295E5473B15B26EC129A24C78B7198D558209E827C38426D747FB0D2B04F1EE7B142B7B736EFF4B819B5420F4642E77181617BEC8074109B463F4C53A6F3507A0B4419B2D7CC0B6CF89FAA2CAEAC17BF19E6A94E0BF346D0F77C47EDB29CBD204483E53853401779AEA0998B993E39EA4C5003326C017A5A3BD0C5591D4F822641FAE9DBDF78B15DC5BA326150F89C864774A8DBF6464B259A29C00D9BCC63F61B3B45FF19E6FD0CDA2BE17608488B0E5C6CC5C596F035C8E580C30FC7C6FE2428F3509511B9D7FE77CF53C5B0E8E66BB573B3D467B74B5493A4E8EA49A79B7E2D36A6C0A600C6B13DC617C3FAF927B2CB251279CFF4228254CB6022AE9D97A36894EBCB305B179284E5D2F330266B2B600E248D3C4B8121A8D698183A38BFB5A40C5E85CB08EF0BFB0242E418D11DD648B9B84E072A70D3FBA8A9B0CEE05BFD71AC945543E306824F9A4DCBA05BBE0027B475A020BD764B53AA5A187C089A2DEF8F3A96D38491A61CE5F3DA625F7F4EF38130B0F5DAA14E2236F4CD95FF0C31E7D6C1CC15CDE7D9D4F95326AE721812458D413CD6C758671C9A85D10F7692CE31A600483F6444F45E74C45B7CF886E63D0158E19C0B87BE6CD9FC4B74D72CB004D3BD7ADF60E162F4967E5EF3BCA0AF2DD7ED1DDE4097B5BA250281DB7E46C22A25A49ABDB1B2D148710128DC1F1A18CD0D762A1D2EB5D5D602336EE3F0A0095592E938A79BDEE72CF801015AD5871A8D907298E13F960A1417FDFA87C3FE3DA9490B73B45326C3161D9DE6460E37208665FDC90CF894A0301198F5FAA5A315FC562B2837194662A58DA13065760571172D42306BB57ECCFA578E9C927C211A1F7C1983DE1AE1EAB0A264AFDC18CD56F14E0429E80B0DDE9A5AF527952A7B6ABECFCB64CBDA3C3E7A024FC5CA3B655FAF5A2787FDB22C1DD3160827C886A119FD2833DA87E60F18B6A969916D35F559BCEA40D6E5E53F84FA5C46DD5DD09D0802A21F64F00EA755F95234AF913DBFB380CC370754448E46EDFC7CCC"; + char testResult[512] = "8D9D660D7BCAB705F14A90CB9A31F7B5206F9936E1B56F2489DA188A90C49CA3"; + + // Get an HMAC GOST R34.11-94 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_GOST)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-GOST_R-34.11-94_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now recreate the MAC in a single part operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate the MAC in a multiple part operation + shsmMac.wipe(); + + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Check if bad key is refused + osslMac[10] ^= 0x11; + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(!mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; +} + +void GOSTTests::testHashKnownVector() +{ + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::GOST)) != NULL); + + // Message to hash for test #1 + ByteString msg = "6d65737361676520646967657374"; // "message digest" + ByteString expected = "bc6041dd2aa401ebfa6e9886734174febdb4729aa972d60f549ac39b29721ba0"; + ByteString result; + + // Test #1 + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(msg)); + CPPUNIT_ASSERT(hash->hashFinal(result)); + + CPPUNIT_ASSERT(result == expected); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + hash = NULL; +} + +void GOSTTests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Set domain parameters + ByteString curve = "06072a850302022301"; + ECParameters* p = new ECParameters; + p->setEC(curve); + + // Generate key-pair + CPPUNIT_ASSERT(gost->generateKeyPair(&kp, p)); + + GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey(); + GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getQ().size() == 64); + CPPUNIT_ASSERT(priv->getD().size() == 32); + + gost->recycleParameters(p); + gost->recycleKeyPair(kp); +} + +void GOSTTests::testSerialisation() +{ + // Get GOST R 34.10-2001 params-A domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06072a850302022301")); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dEC; + + CPPUNIT_ASSERT(gost->reconstructParameters(&dEC, serialisedParams)); + + CPPUNIT_ASSERT(dEC->areOfType(ECParameters::type)); + + ECParameters* ddEC = (ECParameters*) dEC; + + CPPUNIT_ASSERT(p->getEC() == ddEC->getEC()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(gost->generateKeyPair(&kp, dEC)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(gost->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + GOSTPrivateKey* privKey = (GOSTPrivateKey*) kp->getPrivateKey(); + GOSTPublicKey* pubKey = (GOSTPublicKey*) kp->getPublicKey(); + + GOSTPrivateKey* dPrivKey = (GOSTPrivateKey*) dKP->getPrivateKey(); + GOSTPublicKey* dPubKey = (GOSTPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + + gost->recycleParameters(p); + gost->recycleParameters(dEC); + gost->recycleKeyPair(kp); + gost->recycleKeyPair(dKP); +} + +void GOSTTests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + ECParameters *p; + ByteString curve = "06072a850302022301"; + + // Get parameters + p = new ECParameters; + CPPUNIT_ASSERT(p != NULL); + p->setEC(curve); + + // Generate key-pair + CPPUNIT_ASSERT(gost->generateKeyPair(&kp, p)); + + // Generate some data to sign + ByteString dataToSign; + + RNG* rng = CryptoFactory::i()->getRNG(); + CPPUNIT_ASSERT(rng != NULL); + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); + + // Sign the data + ByteString sig; + CPPUNIT_ASSERT(gost->sign(kp->getPrivateKey(), dataToSign, sig, AsymMech::GOST_GOST)); + + // And verify it + CPPUNIT_ASSERT(gost->verify(kp->getPublicKey(), dataToSign, sig, AsymMech::GOST_GOST)); + + gost->recycleKeyPair(kp); + gost->recycleParameters(p); +} + +void GOSTTests::testSignVerifyKnownVector() +{ + // TODO +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/test/GOSTTests.h b/SoftHSMv2/src/lib/crypto/test/GOSTTests.h new file mode 100644 index 0000000..f243392 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/GOSTTests.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + GOSTTests.h + + Contains test cases to test the GOST implementations + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_HASHTESTS_H +#define _SOFTHSM_V2_HASHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include "MacAlgorithm.h" +#include "RNG.h" + +class GOSTTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(GOSTTests); + CPPUNIT_TEST(testHash); + CPPUNIT_TEST(testHmac); + CPPUNIT_TEST(testHashKnownVector); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testHash(); + void testHmac(); + void testHashKnownVector(); + void testKeyGeneration(); + void testSerialisation(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + + void setUp(); + void tearDown(); + +private: + HashAlgorithm* hash; + + MacAlgorithm* mac; + + AsymmetricAlgorithm* gost; + + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_HASHTESTS_H diff --git a/SoftHSMv2/src/lib/crypto/test/HashTests.cpp b/SoftHSMv2/src/lib/crypto/test/HashTests.cpp new file mode 100644 index 0000000..f02adbc --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/HashTests.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + HashTests.cpp + + Contains test cases to test the hash implementations + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "HashTests.h" +#include "CryptoFactory.h" +#include <stdio.h> +#include "HashAlgorithm.h" +#include "RNG.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(HashTests); + +void HashTests::setUp() +{ + hash = NULL; + rng = NULL; +} + +void HashTests::tearDown() +{ + if (hash != NULL) + { + CryptoFactory::i()->recycleHashAlgorithm(hash); + } + + fflush(stdout); +} + +#ifndef WITH_FIPS +void HashTests::testMD5() +{ + char testData[4096] = "EDB39CC3CB5E8FD23A2182FAE8781F4E8E8534C8FE10BDC7ACDB34C4E22E4B60872E51AD092950771E475FB97B05D6203A0D1B3326D9678E44FB40787D8CF16BD3BBE4D4786F60BD8E9766EF1C30B22301FA8F7232358B3C5BE644342499622A5153B29D2E5F8F509771E8A5DE3B3737D30F2AB035262B8D83EC55F683E9B62BBB31E2E1F5E142A13ACB9701E1DE8752ACD492A943C2DB57CF4035BDA9D0519B86847CF74DB2F43CC23016D88EF44BA422710C00AEBB2ABDDED89D92E4BD132CEB87581644198B0D4AF82F3CE161ED03A4E189BE8276243243817F91159BDE294E61400041537618703754C609709846C3EDAE6922B498D24FDC6B9AE702A034BB3A2C6C230E58EE5759DC84AD0B960B111153F6D619E850E36833A26689B4718719EFF3A407B77B0BAD24A17E29B6A29E9125B4CF0DFFEB8D0B03D533ADA43D1F20CFFE0A067E0F6FFF28510148DD72AE33D8B72227523497B84082B682A480FA3B2FE42AAFF49883DAA4DC6826C9593D38002D73FA7AA91B41E828CC34FF12ECC1452B73709696A440CCDF3E6116DA36CB7A01C9E168C3518304721D2CDBC077F4D4B7E8D1A59F954872862F72AC12CB16E33BED8EC3CFD912E36BBF4DA86E31F5F45BE9294550965C7CBC03518AD7C5637A97F7470EDD6E359E82815230CE03AEE9512939A214D017719E5F6B2487E3B468D50DC8EA41EEE94360E77E0EAA9C27DFE2C28D63B7699406E2E6620FE23F96584EEA04034270A2A44096B70017CC2CB197CE8DA3B1924D8D2E86FB40FF59CCFC78B3A4F543068F08C3406DEF52413F95B2BE2AD5DA1ADBB7D95F2133F61AD5518A1BEA018E3C3C0C154EAE56B0B0F4A8818AE47DC618D138245192D055CE4EF8BD1A75030EABAFD66E45B204BA6B123FF54D78F51B6A7DB9B08BEE93E923F9DE553EC0BE4B8BE222998BC792002005ED66C0218902E7DDF6C6D5043A8A9790E438D5BDE37791CDC0DB6C974638884270D4F379DF845281C5F1F8A20978086A9444779D59423B6CEF8175E0BC2C517FA921EC66BE3F11ECEE078553F610D5B65FD293E37717C0CB323A2760646AD56C77A4B96940CF5AD1154A642043E40788C2D367123399FA6015422F5EFEC851EF558ACD4BC31EF3D3EF912241A586E54B97FAE083EE45FBBBED74BC9E3887795FC2EBC5354ACA358EC509F4AB8B2967488D5E5B77DD44EB72E66694A1F490ADEB2848918531B6FA7216C51CDB507598F1AA0985626482D3546BEF5CA3BB409934D11AECBAD47389F2CBCD85FB4DD1A8A6F4D0C28920671A31FFC14FC00FC51296A6182D5A05B16B33232798F0993C78BCC662932E2F57626D639DD00E39B206C1F8A15A19B5DCA9F8B015611AFA47A10A30527F552A22574E15E3577EAD9C7B89782F82D7082D747B50CEFD38C6F17D6269A696F518EE6EAFE1E1EA96FB4D"; + char testResult[512] = "7299FE513582D71A3B9EA1E9F45F95FD"; + + // Get a MD5 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::MD5)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} +#endif + +void HashTests::testSHA1() +{ + char testData[4096] = "0583243FDEDEBF8C9EA4017808B490A2581A5A06B8C2CCA4F2259B7FABDE4BECA9F80C3EFBFEC436CF5F252568CDF55C7D31002456F6FE711D404F9A274037E8D55EC6C55077E4900EEAF6524C44FBFCC1C5C1C6AF962CE22106610A7C8DE7D725BF924B81EA566B952C8723E0EAFA21EB2C6E6F5528A89FC24C478C0600CB4FD482FAFF8507284C5F1E8AEBA9CDBFB3E71D77B775DD7C09E65049423BBAA70499450AE3B46703A4A44AE281C1F0341EDF0473B079C44E0F9EFB4C3683ED706E480C901A16E77B52030A7E46E31991131AED9C98DCA1850A4BD6F35DBCF5A894A8843EE656EF0DC617D923EB38426855FAA2E77E70CE9A8AC81D0F14259A748F9227F732420CDAE5A1CFEA9B541F0B12ADD5D966EBF66613D7FBAF5FFCAC8D625CFA536DBCA8E54B01B237211656F165A8114CD157E82870BCCE6AE8AF5334105B4E50B0A4E4AE5D0A3CC5CD8FF85F7C4D20D2627694B168CB48DB81B5B78C620C7559B2043C268F5D7351256D41FE892ED8EF6F7B5DD8E193EDCD268C55C209DCD0E827FCF76D6951CEBD0065826FBF044ED5818FEE4ECB99973FDB6826BF92488652E804C40D07D4CE43FCB31481667EE637721B91FD38331A98A6E8969D5B1D0690CFA0B500D72BF2D42AD6471FE064496C91126EFCC46B8CD093BCBB70D21FDE1937A888CA08DF3068A858280ABEAF71608BC9229E8E5EFF1814C4887E3A26782A110F347560DAB6B07DB8D063E8343A3FCD99B34C3C3F649096339CA7D39DA6F7B2E489A9EE6CE01C923D45C50350AC57247838E323F1B2A284606E45D60938A6F492545C5EBA0C7396702C0F4E77F36AC9ECE7ADD32FA4EEF7B38F9FF3F8BFB4E05F1025AAB52FB1B4777A4FC4B881EFA484D04397DE4312B7EE2BCEAD0ABAC0513D9C1819F59996AB5E94D48C098634D9907A4CA41B5A900F7CC299937B089A52C221333BF6B35242CA8D552A9CAA3BB18944D5CCEF69E752FA74A8BA3DD58159BAE375944B26A636457C30C451A58984BD6F028C8CBD3ED893ECD2F1536AFF3A97DB92C0E2FC93B9CC3837FDF56E4E3065D10B15F9A5A8925A5F772E4521CDC885180ACE49D98719BCE6770604C11E6DF090C199A5BBF1D695E1D55E2C9E135E89AB26446F6FED3FBD7DFE58EB75CA61B2D3DA4974908C7183E62FDD79C233387C78EDFF8AAC412EA36AD929808023EF04B8C9B7F980CC3FFD50E7356F51FBDC3DE8551C4F5B283D41E861E5604155E81748BF017268D4FBA8D253CA695300F5FB9A51190B24E2B17653519A3FE500B27DFF90A9FDF8404AFA8FAA1C4F738EB45969846E0A18693C06CA5FE2F2B5F7A33974A9453383E558317468B47DDAEE7A2AB90AA2446155CBF5B6473628C1D6BDA9044D4D96D1E3846AA7A65046C680BB173670FC04E5AC7D8CF41C6F233BD6945C0EA90958E9DBFE67D0EBCD"; + char testResult[512] = "9A5BD96DC0CD3B0089FBB6BE7D56BEE638431F5A"; + + // Get a SHA1 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA1)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA224() +{ + char testData[4096] = "8F300FA699500CA5E1E22B38EC06B2EADCE7738CF6A55CB241577D53ED68BD017517C83AEB9CD3A25536FE999B7CD61D9E2BA85C39A7D27CE2CAAC8FE7C12FA1B2905DB85ABF230A813C1A72D2BD93BE0C5A79842FE35C5EF4B2E94524FB9594E3CCC63FE2A4E21D91C25DED832FE8BC9788697051C2042094585187394BD0AFD64FB627F3CCB350874FD0D454BF0254A72DD99ED211F68DC15B94A5682B73B89BF533746E8EEC5CCE45DF55466D7026A95A062EFD49FA270751A8D427095D38FB757FD4D1395B5DC7D302D9CF28C2E2D09796B9E0FC2D1F56BDE005FCD266B097822C170981DE2DB5E92582A612019823A3A062E228AB99AD6A0E47C1DEAC0078460252D83FA11253A3EFD374B2B392F0E27079F9FCACBB8EE6320C7A06327335AB34B757057E6C7FEC5004C4F675D2C4ACC6B359CC13D6F9FBE7E12EA7F6FF753CA8FB68059DB06D9804CBE08AAA55E0F20EFB7094695C1BF0D8E504EAD0836C0E6BB491E1691FDEB9ADFE0C92CED19A612DBCA01FF5A515E32B4EC06BDA00482DE721B6A85F00CAB264B34C5F3749D35603D0216C5AA426BBFF15637D1AE7805ACA572337232C27BDFC9D17D5D129242FD883E3C33250BA089EA03BD794C03D8DB9F57F87DC0A30E37F063B9C4C43518DC9F94E7BB18718D1DC79474CFAF60CBCD5CAA8AAA9FF573E26BB8B722C522ACF561FF34A0716FB7C1217050AD6E8323889B47D7551BC7554909651A9BAFCF5F0FEFD100D35B2E06D89C46E572E3EB5A07FEA702DF10BBCD2CAF2F2A62A9BC162F6369D0DBD9A6D6368ECDAFF4246DEE682C2B20EF4D7BBCCABBE0CD44CFBB531F2190E55C1A650B4D16DB2DA0453B23C4F056C1F791336A7266742976653B2E9377F500AAEFA1EA5FEE3469F4A85A484F69FBFFC1C163F78872AFB79231D9E5B4F8EFE2A9E8487BC33E4EC462F9E451BFEB306964D1F02873EEABCAB0F06361DD463398717537C7C255E3DEF1E9EC1567A600CFEB63F822A3C24B3524225A40F0CE948B0284AEF1F9BBE7618D18839725087DD6BFEE15653B981D6F57ED6685388F3B510140F437E93B92583609D4B873BBA3641B2DB56AB26D3DC27A85866D8F66C4A33D82932ECE277387E583BB20A689BE12B597C6199799A3A53B970596355A46F7F94B9D5E07B09B8C47355CE19D7D2EC1F1DA8F382F7C90ABABDED1D82C8BD673C008E16102025B8C8AD33832953B9E28A1C01353C513D55F4E38C0FBC1FE7C1FB6B93D10B464F851BFE26426BC09C599708CA1CA3413BC4B147CD69A761E688E3846949AC3F455CCDC0DDB4FDBC91D880B38C73B7AD4C8633598F4570E3BCBA3C5E785686E38D2926187CDF0479DF5B818EBDDFDA757C31DF009ED234B3C0F2BC1ADC700FD715AFEE46AE5CBAD02ED086912BE45BE2D61097F008E45067C4ADC4FDFE29220E6CF0C6F7F8"; + char testResult[512] = "A4E71A239CED53E936011DF80B516A07DFF13BB5B05BE43C46C05CCD"; + + // Get a SHA224 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA224)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA256() +{ + char testData[4096] = "C75FF0C53CB345524BF9800FDF53CE448F3369F9CA08C817F8F07AEF0689274527F0AF1EE7FB5AE99B37456765F39880640BF6C5582111753758DF49A9A13B52379DA0C7AE930B03BC57CD819D2EBA0E38AD33D10876608B99A69D0A73F001065276055C4B659F62F77E7232B021BC085A2472293D2D1875028444902AB29D78C9919EC52B33C9F839B1F839C7FF39B68669C925F53AFC865C93D3694E2FD3F29FF0B7773BB412D0FDB1B506A4D501F840D01AE9BF18D7558109B10A6E55CD8CF9A5279D559810A0B08C84C2C8C294AFEC06C6219EB1647A51488BCDDAACE7C652BB0D3F1DC552E4B42BAFF52FD17239F4C08DDDA1BBA97D8D35D3A3DA32D66858B2D320A62AAA7C3909C3A34DCF9DAA69BEC13B7B3EAAEA8A56E2C6DB2507C43BE8990ADC4A281B8BFC6C76FAED50217F109594902FF7E0EDFF5C018B0FC76CACFF84FB9EA97D6D543EDA732089E82FDE3B9D087320014680E5EA2B21B534125806B650F3268DB7951460A9E32F2EEAAF69300E6F0B7F846ECBC2904E93E8D0423FBDCC3E34C5085A97636EA9961B00880BC381E37C3A6E3115256B1A9E1A915A401A8E507F97A09BF3881E852FEA614DF76D709DE6DC0FE54500E0C42132E9ACFFE4A4A98654190FC6C14FC3E5F42CDCCAE0DE05DEF5F6961D7D13DE15376F35142C5846013B7D4A8A6AB363EC7932415C556B83787C86491820AA29C2FE31E39A3D73D710C490D1AF863C4166C2301ECF6967506DCFF6F97CAE63245634153072FE27E9C4B5F90B3C42E4BDB4FB0E85A548CDE2D3B480ABFB1ED6F054017B120E41529909AC055A9F5A29E25D0E5D1A8E8550B9C85C300BBAAE030B22BB646B1FD3A90FA1C242A26071423B3E239EF65BE8B347663B6BF63436AFFD311D10FD24C8E8D05CA99A808C41E6C9C7B283FE5FE9E311642349D2799B6D0CACD5826CC6CC5DDA22FB8BBDD6C66BB722697E4558A75B6D24FDD55631C17FCB591CA3CBA180CEC241B0555A91DF4D47A648A7D901B02C1AB557C4E1CF33E277AFE008D586857203FD6CE695C8EDD446F74056B173D6A0B07A2A58B39366B58BB76AF96DF9C37A5A5E1F8419163CEAA304D451DC38B8F142C422FB475869667D55D88F7C2624FC0B29A958BB4A44C6B0439542AAB02319D46B7E482149DC9A7C7BEBE651C7E8404140601CDB3742F58B6EEDA137FA083BA9D297F91B41B34C3535230841F18B672ED0FD817B7E4E3CD1FC018CDA63C21C3C3ED68228DF85B8C26572D1B14EF10D5D0BAF6F3ED4B9A8C3DFEB4EDEA00CE2DB5903D510432BCBA791C1BBDD2770F2616AF855941E1BD710CEE4F17C4C7A9E283B12DE901A88D634E4ADE69ED529328D64F8069033A6B4DA5D8E0E1C0150DB862AAD54F2827B41CE1F21E3F890033FD46E438615DDC527D6D1260BDB79478D6A0BE2B58174648A2387E3AE"; + char testResult[512] = "3902802C215A5271439FE3E81AC7F21DA55545F71193A8DA8BEB0EAC8046A43B"; + + // Get a SHA256 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA256)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA384() +{ + char testData[4096] = "11FCD8770F582C2D9C860D1EB4FDBFE40C551C6F3AF41A2540A39BA3A121BFEF995F1727A8703C29D0A44EB85B339F27955E1C679796A72980BB1D1BEF4D51A73174A983D36CDAD56BC1EEBA5DDD642094996531EEC94DE2FB6E0ED4F23BCB2F1D0B25505EB16306473DA17F809BD994FD9A737D29819BCCF94CA225D2EBB9D89DDA6E03E80A9DE87E44B72EFD397F9F344122B6591CED9BFDE8C0C42D8C17223A93F33B7D569291F91B619297F233C1454A168AAE126E89B0ED32B0B69AB095A1BB24BB7F1AAF8EE0BDBB43025EF3339F96C9EA352E78BA0661DE896E8F4DFAA7EF623F2B5305AD338448C5FCBDD6CC1F1222ED1D8F4C634B82591F8906DA8DDA9A0FFB0F1499B5BD08239F7EB3A02ACEC60FB76754D0AC5077C3B733D346F0BDE654CD612F60E2284115297A1557679901A911C2AC7323DA2FF3CD57895D7D181AD43AB7068609CE046B96B445EA08CDF50C40DFAFBA9F7082707A813B9C8E4E9D7F0230D5AFE40174693512DE96E3FAB1C8F6548880823645A0AD811694B293F788D0D523EBD81851594733EF45FC763B956044E29B29C195BDB317FBF97F41C601A2873C25557C3149F648424380FE79E4DC407A9CECD8F14B843C642FD9921F12786C8A1C6F8514C99672038693C5CF1FBE91F903E4ABC9E55B967B2F72FDF1A2EC09C14C94C001BAC47A0C36E9E6F34431381069CFD64D85F11285391A4DC7419B2EE8062F344538413E757EC258192B90F2CCC1186AB9A4ED5CE1290644CDEDAF03A4BF3E94B9F9D132ED159CE03586C5A69EF0A471146378BCCE799A3CD8D627B688BB28C9288F44D1218BC34A05BEAA398371ADC60CA8A2557AB69BE7B737F84BFFA93A1E1115F498600F52144E0D61055A2FC0CD45E20962CB2FF475896D733C74C2E95986389ED74B1497A35E73FEE0F36270CC65D76C1FE27A35E8F1FA0C5CA7F2C6003E21BD6677502CE268EB55B16DA863FA291AA111F338F10592AF86DFC297718365C04839748195E20A64BF42020846A46C94F1728549B8310A7FBCBA2C1441B033639CE52B6DBDA69F6ACC57F2DE6BAC57755734AFE4B77869C4D9B0DC56B115476A86A82F816CB148CDFD2B1DCCBEFCD4559B59AA88C6429F4A9EBB43B641144752A5E6F8BE1B739AA69FEBCB8D7439E5D917CA759982146E627FF81E80CEBC37BE0CF2A6C12A3E84A389FFD25013C491AE90A395D4DBCA81340E86848217AC426603CCAC981B5ED701CE9AB2851DC5F2ED72484FE99767C0FDB6F122B0C67926A637B57EC4F047804BC3A9BD55CBD78B83154BC27B6F8A66085EF02A206F329F3B1531ED657C75E29DF4276070AE5054F484A12990A9DD13C112FB6D3D57AE42E6A048870FDAABA48F73E03344C0E13832BAFCA2AF81AF19E5C28983F7BAAA5135803E78FBDDF7FB53C9B9B709274F05C774C77F0B84"; + char testResult[512] = "753659D55E4198325A3FED0A35761EC45038E8963B7525BF00D5A6A5D904DD9FA3FC80AB020185E08B14992ECC36A744"; + + // Get a SHA384 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA384)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA512() +{ + char testData[4096] = "B9D5BD978E1B4A0268331AE4F0C4494EBA71125ED75B9B4244407271A29D93BF5BA0D6641EBF7A210A0905B5EBE675F7B900B89542D0DA6A3952DF9DC5430ECE31F4A5834CCF132724963A088DE43966DC9F46011F2AD458E8FCDBA18F6D183235687A6145401E9FA2EDF60F47F3835D953B5856B1F8308457D9CEC29246DC51F5B42BD5DE38BD89945667579C05756D1C47BB58C2C3D049C58C014C1F6D962BF5EBA1D273F5A7FD6D9291E293CD30B8D8B489E79E54A7A11953EAF4FB6AC7F99910ECE05B511E098B6AD33A599F5A8FA43692FDD9F2A26F316427A2ED1F231E328864CDF9BA2879E0A711F48038E653520C74B7EEA8858F17AC332B87EF4C70A838263C8B17B373161A5A15293D1A7991F0EEAAE0BB69C95DEC22A1CD6808122489703770B5E276735F9D149067A7F3E6A7D10A790253C81778BB79C06D1F98A2CA9C2E8C4BAC0A96F0F9736B85E7BB4F090C5BEB25F087AC037517A9599D94E072D03D9C48665DD17649E001E45966AB8F2C7D24E38AE4F0519F056B034E0ED2CA133F108105BE4823758543791225144AB0B9609F0F861B69EEA8707D6DB9046910F28C6F8E1D47F59DFE9B59F81242FCBE5A71669B90F7B4050E517CF6D3F2FB8759FB7300F12C786D36183FA64692F379D030D0EA90859D9D8E00F27500B41FD716E325E695E3D8EBB40A4E32AFA75F6F21013C8A3261E9C18291DC99142FFF91EAB6C2B55FF5DE03B1DCC88C79635B96F13B66CE6E26A1D5F6154F3C6E5F22AF4B0334FD4521AE57B6B13E2D3B777AF66742635740ED4FF5FC752B908A079A6BBE8499344096549E6FC6FEDBE57AAF2992E7CBB19931F43360415C39D65D2A92775C78DE97C712022460E48651EBDDB9E0527C7EE59F6C817499100C11E884633DC66EF85B176D7A529894CA8F364F559D97DC7CF1769813FB36F8F738E77354C14A560CB98DF92BB5BB16A5A3EDFB75CB78A718C070BE5D37A6F742F88B51BC633FA9E309311BCA908F4D5EE381FB593B7A53E4CE3A529160A2965D0C4CEDC6548D036A1A4FE4576DA9D35E0CDDE9567E792D5C77EFAC17E531F402E0BE99957A7D378E90C009F3231FEE6E3898B5D2C4291EAD396CA748AB0A39469B921BDC5F8066AB7F0D28EE0C502EBC95C2A39DB4241886736F17DE1F33BD384EFDEA951BF775A0D41A499E85D0488016D7A281A9F7C715EBB7CD6AFBA59C1A93A5AEA66D71C3058C5A293141EE4D2C3E65853EFBEFC55912F5C08B9990A66C313F3199C0769CDCA711E877766ECA773EF2FDBC0656B8427CA6442062D911B13F1C2E92D3F0C608B1D8F12914953720021D5648364F953F93CC49946E44FBAF154A2FE3A8055922F784FF9B56D5FAC35B65266A248794101C12750DB8C107D048E551E52EB3952CFA26345B4E21652F5F3B8F85DE04AF9731B75C79DDBD6FE1A5"; + char testResult[512] = "E1483A8525CE39705D14D60D8B19BD89087AED5FE6D8913AF8FC3F6F4EA2C1BB5957E205294B1EFAF20AE5EE39A9522F38B4514C3C15ED70BCBBD5821E385F95"; + + // Get a SHA512 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA512)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} diff --git a/SoftHSMv2/src/lib/crypto/test/HashTests.h b/SoftHSMv2/src/lib/crypto/test/HashTests.h new file mode 100644 index 0000000..dd6566d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/HashTests.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + HashTests.h + + Contains test cases to test the hash implementations + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_HASHTESTS_H +#define _SOFTHSM_V2_HASHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "HashAlgorithm.h" +#include "RNG.h" + +class HashTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(HashTests); +#ifndef WITH_FIPS + CPPUNIT_TEST(testMD5); +#endif + CPPUNIT_TEST(testSHA1); + CPPUNIT_TEST(testSHA224); + CPPUNIT_TEST(testSHA256); + CPPUNIT_TEST(testSHA384); + CPPUNIT_TEST(testSHA512); + CPPUNIT_TEST_SUITE_END(); + +public: +#ifndef WITH_FIPS + void testMD5(); +#endif + void testSHA1(); + void testSHA224(); + void testSHA256(); + void testSHA384(); + void testSHA512(); + + void setUp(); + void tearDown(); + +private: + HashAlgorithm* hash; + + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_HASHTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/MacTests.cpp b/SoftHSMv2/src/lib/crypto/test/MacTests.cpp new file mode 100644 index 0000000..8a3db1e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/MacTests.cpp @@ -0,0 +1,687 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + MacTests.cpp + + Contains test cases to test the MAC implementations + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "MacTests.h" +#include "CryptoFactory.h" +#include <stdio.h> +#include "MacAlgorithm.h" +#include "RNG.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(MacTests); + +void MacTests::setUp() +{ + mac = NULL; + rng = NULL; +} + +void MacTests::tearDown() +{ + if (mac != NULL) + { + CryptoFactory::i()->recycleMacAlgorithm(mac); + } + + fflush(stdout); +} + +#ifndef WITH_FIPS +void MacTests::testHMACMD5() +{ + char testData[4096] = "B64CCFF0DC038F4B4B6C77677B1E89774028CFB6F94EE920ABFABC8C389F7DE287D558664FD05836E854458940A486A367C9B771A7938BE7DFFF2C695BB99CB96F946707FB405A0FA94116FC4002FAD47F813C4DAF6F39B579A2C1E607AF0F80E55FC6742ABB46CF25EFBAEF820DACAE925532E0F2AAAD64D23D0E5682DC38FA47F230EAA299C4D87EB76D45D4B4A08BB47AC873A428708F9D236CF9B11831BC713DB5C8F58A4A4DD228B7A370154CCDB92420B01D0B4141B2CBF05E51D364F7A4D7EE20F1299A697AEAE7341EB6C2F5C458D8AA9A33CE6B2C87B42A9C8EABB3A3311E3828935B8743604895A37D0E9717266872B51CBAB50E9399A0E54457F88DB022CD1859D704FE07C2B530BE14A11072133A9D3A8CD94FCA2B22A320EA08D0292DEADAC4BF705B2CDF71CDC13EC72918F2BD8697BA42AA0AAD62E2D549AC639095EFD2EF606414207CD3770A14FA14AAD7EED197A1A61EBF1FCA89CFE2B69E709C98F4299CF6E1DCF34A98F3C89C6357B5DCDCB335C98EA8DBBA64700EFF9B79CCB875FA49C0C8FA8AA98D6B7B83C3818C4078A8433EEEC71423D9B476029C190ECF1552CF59E1BB2ACDB08663FA792D806E5FF5A6D3E4E09C3F6276663A09D5730A9AAB456D4863F2EDEFEF156A7809AA16D3202AA03C64359BAC628EA1D9ABE2D99999C2891ED49C6081DEA6907C93C5873B4D7880DE271D6016075AFF330FDF221790258A99564F1B51B979DE7997F5FD6676F679B4B14222753547C06960ADCC287EDC29E627FB88BD0E73EBC4E631A58DCA425FADFFEE9DBA177EC182CABA803EEE16636599A88C39A828A5FB206F6DDFD6023F560A421FF3D93B6C4A2A27B78283280C2FD5D249C35270EAE8F8947FA07189BB3A03184C1D8DDB12038184C467EE7DA6CD62F1775F316BE3C2FAB947D49DA19B480E8E4CB4C7818D7769351107386311E5EE411DAC5136869C147DA8E782FA60ED69B13C2DE18CF11FD75CE5F8F16993A026FC3441EE3B23DD6002B8F015E5CC336B5559A427864338C098F4857AA40399916614E061BB176AE4457CA72625A37F08F179A14C39B065CF3283E9425355B6504784C0F4FC1D7932F5C14B43A9CE3604935DE695CDB60B1ED58BD71AB540EEDDF9337B0743D8E624E1A932A69FB1FCA21CFE7F6D2FFDA78F2B8D5BCE01C59BC0A3981BB3BBECF345F43ACD571432B742F80491B490FD71F947480FF9D215EC21237F5AF28C31608DA7A6230CAD24EA799506C8C0B1298E9FD09DA496C6B63710920CC0DC14C00944A7D9B9B751D741A828AB35A5926D3653D45531A4D233DE198439D1946633FF6B91DF0744073CC6E3EC3B177414D8ED2AF30515D8688914667F507667776634A2A11BB68F65B363BD56E8CCF957EB4BB0147862D4C17268AFCE5685C8346E1917B8E8618D3888355CE401AAC5D2DF"; + char testResult[512] = "1026862877813E17E4371095271E1B56"; + + // Get a HMAC-MD5 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_MD5)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-MD5_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate the MAC in a multiple part operation + shsmMac.wipe(); + + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} +#endif + +void MacTests::testHMACSHA1() +{ + char testData[4096] = "EA9E200DE69522895F516F1380536406D205D72B31ACB902CC582B12696579826B5AF47892C4831D8AEBBAE039D87F82096364782B49E2E896AB8077E773AB61E05A8223BF17CBF37AB1BDDA70C9B10D9943AF4109571ECFB029156889249B309EC45A34E2D701F1F4093610A7064B69E7FAE5FB39E39EEF3CAA9D64E50DA8822DF4C8DFA064B165ECA4C9CD2A6AF1A251A1F5D4004123B67A7CC3FAB7462AD43535018479BDFD24A2C4A1C4271F907E40E2057A6271BB2BC9740F753CA3692E7ACACE547E64B9FAE79A96DF3DDFCDA7FDCCC7612E41B0B9BBFA3BDE2102F322E8EC42DA2679531782920FD2E7385F6AC887D578B9D844F6A7288EDF613F3663EB538DBFF14EA29AC8D2F58C703303CD370F55BAF02532A0BCB2F80673F6D84B04A5C3EF9E05B640B4CFFD903272089B9960B54197CB5D10C23BAFEA72EFF79C65E0EABEC628EEB5850AC4A23DC80E857EBA5EC5EDB9DD0A5F391B7F8BD354EC976881C157BD5735AD894F020164A9DF214150C5788BC1CF73C15437DBF21D791C75074DF4B51B5C0ABDC79063AB7B7CEDEDC6412F9FB1F6CA171BE6814E033F32CF1F08236A3DD657DB96CCF7A35434C4D0ACFCA81546B4138A6EF6987A874111946010F78074E69BA83E3F395D1C239A122B259F48140E4B80157738A5D443E1762C55EBB67791D5297B3E900B0B53CA7433FB61D2D03C3B34772C5DF77711437003C6DFF4B03DC0B713491F526F9AE3260F903EF9A1BED641E1B262103D395ACAC3FE6F6F1436F0CB3A13AC69C60101EC394DAFFCAD8EED23893C4BC30485FC68854447A9930C0F4FB9AC5B72EF6512278F09F5A024C7CF5C5617461751CE193E54051AE93DF136725642E1DB98842BAA8B8F6231181F0BAA8393FC2EDB7CF0832BA1FDB76A46C8059732B7492711AD1A12BA584D49885E263789E27664B3893EF2DE5C010C093DE1A735D806E4D48C36A0995EADF011FB50D0CA97AFF26B4698524B9F75386897940434A0A38EAF513845BF0F024014001180C651F76B9E0ECA6499F177A1079395C1785B856D5762550EAD2B47B15AF0A6BFBB1B597E72B9E5E6F61769C27AFC29E4D8A523C89D1D2E5E59B57DE89BE04BDC1DCDA0476A157BCB4DA2F7AC0CAF9351772652E2E5B6261501BDF42C23EA9726CB6C258EE9511684CFEECA1C0598D372808002E250EDD4019F85630FD499C35016B8A99C6BF78E69053B4AE7BE6B84009B505594603B363037212DAFCC669F7482995C74A7CC225245DC2E7D4CACC8A59F67513E1D788F0218DA902F440CD2FEB6C2A90A653B0C2DBE45CC67B47863C1090F3F41AFEA9C53CE5C61A7E6B7212EE3BBE67ED91EB1BA006A931055512046779935F84D7CA306C7F9F3894F91F51EFF6005F5A8BD9DD8828BCEA1C4CC6E5F22CE7F14C0A942243C1205FD7697F09C333AE0B263"; + char testResult[512] = "C2FFE4BF83A6FE299CA4A187157F2442EC1527CE"; + + // Get a HMAC-SHA1 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA1)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA1_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now recreate the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate a wrong MAC + b[5] ^= 0x28; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac != shsmMac); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA224() +{ + char testData[4096] = "83E369A9F34D645B7E1F2F7BB676A4DFD36C411D5472A9AC6F3945EF5C9A561BB040C38F2F321C582882820C7F44D48CDC5BB84F41818F4AEB226F63078CE131481D26F26C61EE52BD1BFB60EDEDE1E03A8656E87D5662EE0C0AE085E56E488325512467DAC43E99484A16FA419D6704922C1ADE06F7D1188DBEC88384CDBFDCD2E74787AE247A8027EF60383B3B0A7D0D3ADA95BB3AA5F0821AF050A9709C75673F3926CF9AE029158D684F470DE3EE6B00BBC90F85CD6E634E86B67E4D8EB4251B472B02D167790C6E6C38BA9FE39880544EA66EB4C0BFF8AFEB9AFC40ADC24DF191744482F70793CB4A802CF1AB58562CC26D1CAA2E80375BA45507C3E9F7D99223E0E7FE93CAC58B7B0C69231162D2D7DA75EEFD59452642CDC5AA4A118B6D4AD00E8368A44988201C6286CAA8612BCFFF714855DE1E053AFD2EEED9737459540E45AEAB26999C0951228716AF02F0D35264E3411B03D222F331A4695D6DF4E9EE35D5B1015FF0BE46081D7CEC9137824217A711F015639BE76223845F1C2A25A10D29B637C5124CF50AB0CAA1E33D75843D00EAE69C3A189D463377731C3197BF44523936C4F84F143759E3D58891F7B3B51C858EE29BC1DF214AF09C93148172E842A7FC0078D4E106324AAF8862B845F290FE831037B2EFEF2528DF070DD7B1ACD67762CF1071B96FB95C5AA14F7AE13103AF45A1CF3C42C5D53CB5B954F97BA223E70E0098E224BEF8F5430D027B510DFBBC35EE5F9170E4A43BDDFCBAE8B82240DB870B6C7C7E21E21234EFA62F1582A9D150CCE1B8822BD77ED8288B20883AAEEB5BDF9D0EBB8D3FF47DD51B99E9BDB8B8A87D0536CC25D4939ECB13F7B4F7DF5F0BE8231CF3F53CE52D16A29825739B26BA4082975583967180F787ECF98AD956A9CE53759E20960752938C142DF80E57DDCA236A1F596031942016442002683865EDB210073797547D83CE77D3D6C39E2B9034E685BD28D365992E821BECAFC6DF2B60EAE9777FEE7879B176CC602501BA0B0BCB434DFA5517F8D6172647364F235B3C9BA0B1B90FE0FD67CF6650C2D8D2BC08D127DF0AB887F69CDD81D03B4CC7F44A4362C90BB38556D081E51EABD9CA3AA6C877C42FD1B001C030D0B281590696B5BB9C6A78CBE356F7AC72F525300FD13E24755294712DDF48D1AD19F844120306DC99D8CC18516A23BD022CF9DC9CACC168ADDE1C15337F15B3FBEDE4BFA498F2F963E14B7E66CD737A5485227BA1BAA7668D97C58DCE40EE7A843A5E6EB591FF91D6A6292C8A3E95A0B23C1F0B8815BE526EE7C49B5153264BC1207013EA85E9DA37F19BD50DDC9F0A5B9AB4FCFFAD2840B5A8856882E8DF95362DCA13C15328137A2A8318884FCF4D05236CEE9985DB1BA873A9AF5B33E317FA2C0CB94E7C18E46744A374C19D8C9B2788FE50C9E4D237D290555E1077"; + char testResult[512] = "4B089658FF932CA07BF7C42E6EC46BFF560BCAF295826D9D3C0BAE1C"; + + // Get a HMAC-SHA224 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA224)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA224_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now don't verify a MAC with different input + b[600] ^= 0xff; + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(!mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA256() +{ + char testData[4096] = "FF7E669D7764FABF6E3550E192E660DF1EE237B49F9473D757DEFA1400534F57C81E8B0E99458F74E6F57A5BB71A50D1EF61EDB3B3FB4BCA57896DFBA50C6C55B04D4C8C804DB8EB2A273E25F49AE2742D2AE430BE9A3A07715AF6816E818B63BB1FF8C876A921CF931F693E624CDAD4B54F3ABBEE4A09BF39E0FE3A313B20CD3A36B0EBD677D9D4D7C576B5EA244CF0436110D9D66110C95BE187D6EDA1E81A4456231BE32A1B5F4CDC02B2DA679322AEBAE0B795763888F07F0222ADBF824F31AEC7B80625DC36DA1F0C3DD20C6E8F79A7FA2D286119894E611EE550364428723E9C33A573F18D02F9DC90ED215EF08C95DB1CED68DA864732BC9A56B8B191815BCC12075641E3E87F46EFD3726BC1D6F47AF7BC573C554279C041C7FD5E924093241855507EE2A837E2CE62E7A9898712EDF593217B6425B3EB855D53D31F38E5A0736E34844AFCAD58A15B06D357697DC921C2FCA77091BFC207B0B4F1FA94F923B05817211462104287B43CA72986D9E6E393C9A075C267B2C1706CAD136E9F549A83E58315DE8D0B67852006EFE8B6E0773519FE6DB316EA596E1998B79C19152AADDDF8E025E7EDCB16B5CCBA2C9F990605A6969D3C667D6EDA1DA5AFF476661349712CD73F707BB0FD6F8BF0C13A90DE9C1C5CE9FB696C22849C1205C8435C818E2EE03F2235B502E0C24068B8687AF9ED065910535072DABB83F651FC60E005BEF909F6EE308B37E43DA01366C062168007D733D5EA4A610D1307BA087E8F883864140BBB02E523997A0D83E9BF289B8EC9F83F57FF553485409B0D82E77F32BD2D06A130103B9F3915730EE8BC3FB099B74AE8B32C478A83D0BAD2281C279D6B802F42A80E179F4ABB69AD485BBAE348C6F774285870F53699500CEC045B9521CF22826FAFFBC4EABE9D856B28DDBC6D2A0F318AE9475E82DE2CA6704B743397EFE45F825019B58D9E671181512D780B1BA34D059BFBF8B9B232E337335C1045682635CEF8D3CB1C744D3A7791F5DB323EF8DE768C63931266EAB0DFACAB0F99BC9C5DA234FE48ECDB23A5FDA2E92EC10AF7476B07C4BB85BDD0600B49F41585F9E0DB2B276BBE0FA7C5792B65012B6564561E4814E8D1EE706935A45F969C9AA110A630E354C7243E21436A180046605FE5D31008045A5C4AB4FF5C23585D77D6C839875CC2E960436A3D90F9664D5522EAB08867B95F9641DF0C81D59DCA8ECE8709A3F521532041BDCF7A7535F940BD3569FD2145A1B34E955E04F66E0CA809BA3FA6A347FD0CB69DADBA93DC03CDF547A96CD3159ACA61EFE20F9A566316BB9C746EB851CE51F04823667CDA0D898253BB10C1C5220B2C30461A49C5FF0DEC38264786C6125720B3768629ADABCF694E01795F618FBD0ADE5C91CB5A981BBA581A9664F51DF758D7300E081E57CE20C8A7210BC3558AD240B7"; + char testResult[512] = "90A49F8EB80D8ED405EFC8D658FCB9102314598939DCAA090756668056B0228A"; + + // Get a HMAC-SHA256 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA256)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA256_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult); + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Check if bad key is refused + osslMac[10] ^= 0x11; + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(!mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA384() +{ + char testData[4096] = "7D4C4274CFAFABE3605DE7E35B43F10251A441A6F4B03EE142B9EAE3DEC2E30E1A47FBE779D716427B108CCB2A2C2D7561B879B1C021E00E0498D91859BA3E7851EF3FC25A1BC6EADA8524EAEEDCC0E752AD90DFD0EA2F04B71B8ABF56DA85E4D070C91EC4B7723A02C3B52DAE31EEAF8E397CC3E92FA31E5F3292D8C9F45D459D8D1105E539D3979ADC01EB4E0C90BC33351295628BD0C2E1B4B13764EDD66BE9AD67AA7B4A7780264B0A3DBE099B190D25649B692401E0B758AB2A281B2E1AC9B4F7EE051C1B98BE92463F314A86A7FD40A4683A82457699F514563C70F1231C0B667C7B8CAD5910334CF894A9810D7C7C6DFC1E904D8512813A84911580C2AC56BB005A4FFB512A1290501AE795C832C0BF7DEBCD9B1D84CC0BB5B5F19D02FDBAB01F7B7CA47C99F3CB7D4F0D35622C267EBDADB2D089D0DA73FEA15A25C873C27EF72A84F99EC4E6980695BA6468B34B5AEC0746219468FEE88277739123FB51CEBF264140FFF27B94D6F751F26F0BC27387A2EFD038EEE43013AFC8FE94BE8E272B28ABFE2160BA81416113CBC2A1ADD96DD23F7107F4771CF2016501A8918A9A71C476CEDC10BB355BC144C818FD620301793CB16372A80881C5DFE387619ED651626CF44C8EDA8DA5BA8A6895148EE36037D4ADDBC13C5681935EDC5BD9B35F8E91B84C1F593B3E89614879CAE4DF4413E13655079F3CE21449CCA19E0963C925A75BC294F343016518D2F8FCB13ED38D574232602AD2416E94ED7735680439CE042145552F352156FCA722B31BFAA289C3711F170A845143ADFEF49CA53278358A7FECBD605AE9899192990D728CA37218B65DD9978EC4345100E174F3D04A0C8A5611263DABF7DA0BC6CE50BCD338830688B697FEB71909D1A2E09B62C5C4A8C1069C50C8DD6A432ED2B429F6BBFC304D0F0A35167BBDDCBC7F78959058393BC812820AF4917C56EA9233A1567608534F93857EA783B537CE294B4778E4B5D30D5836AE1F0D25B663A62512D2488E959D7FF000F8A70F31CC4CABB51D6F57A842AEABD707122935690F78F1F8BD7EC8544F1E70B9D6D53C50632F4DF5F0BC75630B427B28BAF2249C72F5864A3CE17627BA4F16F8FF13FA19DDF83736B171C024C95EFBC5D90615C495C2B02685C24C6E64E19C804B1DC138B5BC52A6969C4332F6113ED8C38F03A0107513C611A6FF013D2FC0B00859A6A5DFB8626002EA0126D477B5F9C7B5BEAB61A13AA8841A4C11E9DFB6A7164BBC2D40E940D9D10C56D58FBC76B92EA68425C2FF48BAE0CA2AF6F1CFBFFBBD855688C3960538E2D87088472CD73AB6D0FB86D9411310F5311EFCA3B89949A87D408B86B96C29C89A0180AF8957944E2A385A221081870CECC995FFDDD6994B0856ED0DC6303F7FDE5072F0B3D68BB132B0C5D3113939D614677720186052F4F90DD60A1CFD"; + char testResult[512] = "AC387A4BB1E4E078C43C69087C206F49F56EC63CE244A429DA56B8EC3CAFBC987090DA7A8F6470874CA6049D20AC5154"; + + // Get a HMAC-SHA384 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA384)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA384_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate the MAC in a multiple part operation + shsmMac.wipe(); + + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate a different MAC + b[100] ^= 0x42; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac != shsmMac); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA512() +{ + char testData[4096] = "A7A3B0B40CBAAB9B58F6946D9D15870B56E6832DECB708949EBF98DC4EC9C0AF477216C542A98A3646B6ABB72D89E6B3F18201CC75E93B37C2E8EADAD6827FBBFFD220642A92CABB587B27590ED204F8B2C926777C3DC9E5273CBB38582C103905C074002DAA2D8D16DD907BEFB4C51B49C464FF22B93269274291D1254889E3F677FBA6929AF472AECC02DECF822EABB2F05311E0BA8600B58075D4E49837F81C9565E37EAC96B9C2F3C08E3D818DD507D0CC8064C8CC7553D5A17204F4B92B74E5A441CF9142ED059DB1ADA76C799B10178FB3E76E4E3CAC6B1AD8648D522DCA6C93200E706D947E15422E1CC47742CCBF8E2C1E50492AFFA49BE22D5E34B0ACA62744626E2EF7014EAB17D8E538324D9A764501428A53593D23E3785831C1262F220883E2DEEFC66584A3AEC1F35998F842C5298A5E28653CF40F21C6E2383086C266E2902272198D45B38308904F5D2F614A6857E027D133C5455E75B16B9DB124755ADF06B16F04872D74D1A90F36709D8263B1190D625849F017930763AC1EA548DEC56BFD46D09F32D6ABAE96A778B39FBF22B1D6B3CA43F8E7ED32DB2254018FB1999ED0C4C3CDE710899CB20AB5E1CA706DA3E4E8E65253782379B49B7DEFE4E26DD498A935057E91B8FFB8B110336A554A6C61C26C2DDEEE8631926F8A706171B309B99E3B24030C17609340EBB82C4129B172B64CE6249FED00F05DCD624969BC1E4A29ED028C9821A812CDC310A974B959B29E30888887D9A8688E92F85E2A1683C5E993BCC584979F0B3F7DBE34295E2D852B6444EC4152A0C40F3113B402027E323231FC2EDD8078D6661F598588F68FB83DE9C2CA1491107E1F7B676BE16AA6C62B2FF86056905CFCE1FA57065B20A87B15BF1EADAC5FD94F5368451CE8CC2D363BC184A6E87D3D088CBCDE259845E4046D314660B1C1D4AFC7CCC37C7B1B8BBC7A54B63FE61FCD082966425AC3795F08BE7AFD6F9C66F2C3C50DD1EB6B8F8FC3C1A6A298A442EB6FC14AA906A7DA7854B53205E0A8F91C8D6CC3C41F4795FA70E14BA876548022733E61972F0351BC4187FFDE18E776BD68C5E947D2F0B19206D34770BA8ED63874639BBCEAA8D59771A02AEE654D20C69ACD8D16C42BAED6BD1AC51134F49C2A1D685B045527D4A86A7656439A2587F48F5AC43C5094DC680ECE19EBDD53B39F3B84F36D363D8CE464A20DE7ED50C6E32D5C7A9C3868D9823DF0E0A5FD824D239F67C41BC5AD3615AB51EA8B1A2C50B6D4C8F196F1278D9747B8C0B941509850052E63467950EBCE7B56D5E5C481D39E3958C51AE1267C075D8E62EC7F15400A5B4B91B15789015FBCCCC8186DC888CC0BC70326F1800FF56B01BC39DD1C2421BE6E142627B24822790DA36AD9CEA0661FAA03074FAA6F9EBC243DDCB249334B13D31DC19C0F03C6923CBFFEC6FAA29255"; + char testResult[512] = "93E3A4336693965FEEC902F3BDDB064DD63D83EA1E46AA13DA209F8F000C15F366D3F9BE4F8AF189EA96D191D0BDE4CF0FC6C462C214B55ABF78F33BD6DF3DD0"; + + // Get a HMAC-SHA512 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA512)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA512_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult); + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACDES2() +{ + // Test vectors from NIST SP 800-38B + char pk[33] = "4cf15134a2850dd58a3d10ba80570d38"; + char testData[4][2][256] = { + { + "", + "bd2ebf9a3ba00361" + }, + { + "6bc1bee22e409f96", + "4ff2ab813c53ce83" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a57", + "62dd1b471902bd4e" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51", + "31b1e431dabc4eb8" + } + }; + + // Get a CMAC-DES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_DES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(112); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACDES3() +{ + // Test vectors from NIST SP 800-38B + char pk[49] = "8aa83bf8cbda10620bc1bf19fbb6cd58bc313d4a371ca8b5"; + char testData[4][2][256] = { + { + "", + "b7a688e122ffaf95" + }, + { + "6bc1bee22e409f96", + "8e8f293136283797" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a57", + "743ddbe0ce2dc2ed" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51", + "33e6b1092400eae5" + } + }; + + // Get a CMAC-DES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_DES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(168); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACAES128() +{ + // Test vectors from NIST SP 800-38B + char pk[33] = "2b7e151628aed2a6abf7158809cf4f3c"; + char testData[4][2][256] = { + { + "", + "bb1d6929e95937287fa37d129b756746" + }, + { + "6bc1bee22e409f96e93d7e117393172a", + "070a16b46b4d4144f79bdd9dd04a287c" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411", + "dfa66747de9ae63030ca32611497c827" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "51f0bebf7e3b9d92fc49741779363cfe" + } + }; + + // Get a CMAC-AES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(128); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACAES192() +{ + // Test vectors from NIST SP 800-38B + char pk[49] = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; + char testData[4][2][256] = { + { + "", + "d17ddf46adaacde531cac483de7a9367" + }, + { + "6bc1bee22e409f96e93d7e117393172a", + "9e99a7bf31e710900662f65e617c5184" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411", + "8a1de5be2eb31aad089a82e6ee908b0e" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "a1d5df0eed790f794d77589659f39a11" + } + }; + + // Get a CMAC-AES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(192); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACAES256() +{ + // Test vectors from NIST SP 800-38B + char pk[65] = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; + char testData[4][2][256] = { + { + "", + "028962f61b7bf89efc6b551f4667d983" + }, + { + "6bc1bee22e409f96e93d7e117393172a", + "28a7023f452e8f82bd4bf28d8c37c35c" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411", + "aaf3d8f1de5640c232f5b169b9c911e6" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "e1992190549f6ed5696a2c056c315410" + } + }; + + // Get a CMAC-AES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(256); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} diff --git a/SoftHSMv2/src/lib/crypto/test/MacTests.h b/SoftHSMv2/src/lib/crypto/test/MacTests.h new file mode 100644 index 0000000..9e6fa99 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/MacTests.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + MacTests.h + + Contains test cases to test the MAC implementations + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_MACTESTS_H +#define _SOFTHSM_V2_MACTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "MacAlgorithm.h" +#include "RNG.h" + +class MacTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(MacTests); +#ifndef WITH_FIPS + CPPUNIT_TEST(testHMACMD5); +#endif + CPPUNIT_TEST(testHMACSHA1); + CPPUNIT_TEST(testHMACSHA224); + CPPUNIT_TEST(testHMACSHA256); + CPPUNIT_TEST(testHMACSHA384); + CPPUNIT_TEST(testHMACSHA512); + CPPUNIT_TEST(testCMACDES2); + CPPUNIT_TEST(testCMACDES3); + CPPUNIT_TEST(testCMACAES128); + CPPUNIT_TEST(testCMACAES192); + CPPUNIT_TEST(testCMACAES256); + CPPUNIT_TEST_SUITE_END(); + +public: +#ifndef WITH_FIPS + void testHMACMD5(); +#endif + void testHMACSHA1(); + void testHMACSHA224(); + void testHMACSHA256(); + void testHMACSHA384(); + void testHMACSHA512(); + void testCMACDES2(); + void testCMACDES3(); + void testCMACAES128(); + void testCMACAES192(); + void testCMACAES256(); + + void setUp(); + void tearDown(); + +private: + MacAlgorithm* mac; + + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_MACTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/Makefile.am b/SoftHSMv2/src/lib/crypto/test/Makefile.am new file mode 100644 index 0000000..bf63ae6 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/Makefile.am @@ -0,0 +1,39 @@ +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +AM_CPPFLAGS = -I$(srcdir)/.. \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../common \ + -I$(srcdir)/../../data_mgr \ + -I$(srcdir)/../../object_store \ + -I$(srcdir)/../../pkcs11 \ + -I$(srcdir)/../../session_mgr \ + -I$(srcdir)/../../slot_mgr \ + @CPPUNIT_CFLAGS@ \ + @CRYPTO_INCLUDES@ + +check_PROGRAMS = cryptotest + +cryptotest_SOURCES = cryptotest.cpp \ + AESTests.cpp \ + DESTests.cpp \ + DHTests.cpp \ + DSATests.cpp \ + ECDHTests.cpp \ + ECDSATests.cpp \ + GOSTTests.cpp \ + HashTests.cpp \ + MacTests.cpp \ + RNGTests.cpp \ + RSATests.cpp \ + chisq.c \ + ent.c \ + iso8859.c \ + randtest.c + +cryptotest_LDADD = ../../libsofthsm_convarch.la + +cryptotest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install + +TESTS = cryptotest + +EXTRA_DIST = $(srcdir)/*.h diff --git a/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp b/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp new file mode 100644 index 0000000..da793b5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + RNGTests.cpp + + Contains test cases to test the RNG class + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "RNGTests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "ent.h" +#include <stdio.h> + +CPPUNIT_TEST_SUITE_REGISTRATION(RNGTests); + +void RNGTests::setUp() +{ + rng = NULL; + + rng = CryptoFactory::i()->getRNG(); + + // Check the RNG + CPPUNIT_ASSERT(rng != NULL); +} + +void RNGTests::tearDown() +{ + fflush(stdout); +} + +void RNGTests::testSimpleComparison() +{ + ByteString a,b; + + CPPUNIT_ASSERT(rng->generateRandom(a, 256)); + CPPUNIT_ASSERT(rng->generateRandom(b, 256)); + CPPUNIT_ASSERT(a.size() == 256); + CPPUNIT_ASSERT(b.size() == 256); + CPPUNIT_ASSERT(a != b); +} + +void RNGTests::testEnt() +{ + ByteString a; + double entropy, chiProbability, arithMean, montePi, serialCorrelation; + + // Generate 10MB of random data + CPPUNIT_ASSERT(rng->generateRandom(a, 10*1024*1024)); + + // Perform entropy tests + doEnt(a.byte_str(), a.size(), &entropy, &chiProbability, &arithMean, &montePi, &serialCorrelation); + + // Check entropy + CPPUNIT_ASSERT(entropy >= 7.999); + CPPUNIT_ASSERT((arithMean >= 127.4) && (arithMean <= 127.6)); + CPPUNIT_ASSERT(serialCorrelation <= 0.001); +} + diff --git a/SoftHSMv2/src/lib/crypto/test/RNGTests.h b/SoftHSMv2/src/lib/crypto/test/RNGTests.h new file mode 100644 index 0000000..1391d81 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RNGTests.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + RNGTests.h + + Contains test cases to test the RNG class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RNGTESTS_H +#define _SOFTHSM_V2_RNGTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "RNG.h" + +class RNGTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(RNGTests); + CPPUNIT_TEST(testSimpleComparison); + CPPUNIT_TEST(testEnt); + CPPUNIT_TEST_SUITE_END(); + +public: + void testSimpleComparison(); + void testEnt(); + + void setUp(); + void tearDown(); + +private: + // RNG instance + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_RNGTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/RSATests.cpp b/SoftHSMv2/src/lib/crypto/test/RSATests.cpp new file mode 100644 index 0000000..6af1e19 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RSATests.cpp @@ -0,0 +1,682 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + RSATests.cpp + + Contains test cases to test the RNG class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "RSATests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#include "RSAParameters.h" +#include "RSAPublicKey.h" +#include "RSAPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(RSATests); + +void RSATests::setUp() +{ + rsa = NULL; + + rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA); + + // Check the RSA object + CPPUNIT_ASSERT(rsa != NULL); +} + +void RSATests::tearDown() +{ + if (rsa != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa); + } + + fflush(stdout); +} + +void RSATests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + RSAParameters p; + + // Public exponents to test + std::vector<ByteString> exponents; + exponents.push_back("010001"); + exponents.push_back("03"); + exponents.push_back("0B"); + exponents.push_back("11"); + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); +#ifndef WITH_FIPS + keySizes.push_back(1025); +#endif + keySizes.push_back(1280); + keySizes.push_back(2048); + //keySizes.push_back(4096); + + for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++) + { + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + p.setE(*e); + p.setBitLength(*k); + + // Generate key-pair + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + + RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey(); + RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getBitLength() == *k); + CPPUNIT_ASSERT(priv->getBitLength() == *k); + CPPUNIT_ASSERT(pub->getE() == *e); + CPPUNIT_ASSERT(priv->getE() == *e); + + rsa->recycleKeyPair(kp); + } + } +} + +void RSATests::testSerialisation() +{ + // Generate a 1024-bit key-pair for testing + AsymmetricKeyPair* kp; + RSAParameters p; + + p.setE("010001"); + p.setBitLength(1024); + + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + CPPUNIT_ASSERT(kp != NULL); + + // Serialise the parameters + ByteString serialisedParams = p.serialise(); + + // Deserialise the parameters + AsymmetricParameters* dP; + + CPPUNIT_ASSERT(rsa->reconstructParameters(&dP, serialisedParams)); + CPPUNIT_ASSERT(dP->areOfType(RSAParameters::type)); + + RSAParameters* ddP = (RSAParameters*) dP; + + CPPUNIT_ASSERT(p.getE() == ddP->getE()); + CPPUNIT_ASSERT(p.getBitLength() == ddP->getBitLength()); + rsa->recycleParameters(dP); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + CPPUNIT_ASSERT(serialisedKP.size() != 0); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(rsa->reconstructKeyPair(&dKP, serialisedKP)); + CPPUNIT_ASSERT(serialisedKP.size() == 0); + CPPUNIT_ASSERT(dKP != NULL); + + RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey(); + RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey(); + + RSAPublicKey* dPub = (RSAPublicKey*) dKP->getPublicKey(); + RSAPrivateKey* dPriv = (RSAPrivateKey*) dKP->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getN() == dPub->getN()); + CPPUNIT_ASSERT(pub->getE() == dPub->getE()); + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ()); + CPPUNIT_ASSERT(priv->getPQ() == dPriv->getPQ()); + CPPUNIT_ASSERT(priv->getDP1() == dPriv->getDP1()); + CPPUNIT_ASSERT(priv->getDQ1() == dPriv->getDQ1()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + CPPUNIT_ASSERT(priv->getN() == dPriv->getN()); + CPPUNIT_ASSERT(priv->getE() == dPriv->getE()); + + // Serialise and deserialise the public key + ByteString serialisedPub = pub->serialise(); + + RSAPublicKey* desPub; + + CPPUNIT_ASSERT(rsa->reconstructPublicKey((PublicKey**) &desPub, serialisedPub)); + CPPUNIT_ASSERT(serialisedPub.size() == 0); + CPPUNIT_ASSERT(desPub != NULL); + + CPPUNIT_ASSERT(pub->getN() == desPub->getN()); + CPPUNIT_ASSERT(pub->getE() == desPub->getE()); + + // Serialise and deserialise the private key + ByteString serialisedPriv = priv->serialise(); + + RSAPrivateKey* desPriv; + + CPPUNIT_ASSERT(rsa->reconstructPrivateKey((PrivateKey**) &desPriv, serialisedPriv)); + CPPUNIT_ASSERT(serialisedPriv.size() == 0); + CPPUNIT_ASSERT(desPriv != NULL); + + CPPUNIT_ASSERT(priv->getP() == desPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == desPriv->getQ()); + CPPUNIT_ASSERT(priv->getPQ() == desPriv->getPQ()); + CPPUNIT_ASSERT(priv->getDP1() == desPriv->getDP1()); + CPPUNIT_ASSERT(priv->getDQ1() == desPriv->getDQ1()); + CPPUNIT_ASSERT(priv->getD() == desPriv->getD()); + CPPUNIT_ASSERT(priv->getN() == desPriv->getN()); + CPPUNIT_ASSERT(priv->getE() == desPriv->getE()); + + rsa->recycleKeyPair(kp); + rsa->recycleKeyPair(dKP); + rsa->recyclePublicKey(desPub); + rsa->recyclePrivateKey(desPriv); +} + +void RSATests::testPKCS8() +{ + // Generate a 1024-bit key-pair for testing + AsymmetricKeyPair* kp; + RSAParameters p; + + p.setE("010001"); + p.setBitLength(1024); + + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + CPPUNIT_ASSERT(kp != NULL); + + RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + RSAPrivateKey* dPriv = (RSAPrivateKey*) rsa->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ()); + CPPUNIT_ASSERT(priv->getPQ() == dPriv->getPQ()); + CPPUNIT_ASSERT(priv->getDP1() == dPriv->getDP1()); + CPPUNIT_ASSERT(priv->getDQ1() == dPriv->getDQ1()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + CPPUNIT_ASSERT(priv->getN() == dPriv->getN()); + CPPUNIT_ASSERT(priv->getE() == dPriv->getE()); + + rsa->recycleKeyPair(kp); + rsa->recyclePrivateKey(dPriv); +} + +void RSATests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + RSAParameters p; + + // Public exponents to test + std::vector<ByteString> exponents; + exponents.push_back("010001"); + exponents.push_back("03"); + exponents.push_back("0B"); + exponents.push_back("11"); + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + keySizes.push_back(1280); + keySizes.push_back(2048); + //keySizes.push_back(4096); + + // Mechanisms to test + std::vector<AsymMech::Type> mechanisms; +#ifndef WITH_FIPS + mechanisms.push_back(AsymMech::RSA_MD5_PKCS); +#endif + mechanisms.push_back(AsymMech::RSA_SHA1_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA224_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA256_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA384_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA512_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA1_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA224_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA256_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA384_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA512_PKCS_PSS); +#ifndef WITH_FIPS + mechanisms.push_back(AsymMech::RSA_SSL); +#endif + + /* Max salt length for SHA512 and 1024-bit RSA is 62 bytes */ + RSA_PKCS_PSS_PARAMS pssParams[] = { + { HashAlgo::SHA1, AsymRSAMGF::MGF1_SHA1, 20 }, + { HashAlgo::SHA224, AsymRSAMGF::MGF1_SHA224, 0 }, + { HashAlgo::SHA256, AsymRSAMGF::MGF1_SHA256, 0 }, + { HashAlgo::SHA384, AsymRSAMGF::MGF1_SHA384, 48 }, + { HashAlgo::SHA512, AsymRSAMGF::MGF1_SHA512, 62 } + }; + + for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++) + { + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + p.setE(*e); + p.setBitLength(*k); + + // Generate key-pair + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + + // Generate some data to sign + ByteString dataToSign; + + RNG* rng = CryptoFactory::i()->getRNG(); + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); + + // Test mechanisms that perform internal hashing + for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++) + { + ByteString blockSignature, singlePartSignature; + void* param = NULL; + size_t paramLen = 0; + bool isPSS = false; + + switch (*m) + { + case AsymMech::RSA_SHA1_PKCS_PSS: + param = &pssParams[0]; + paramLen = sizeof(pssParams[0]); + isPSS = true; + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + param = &pssParams[1]; + paramLen = sizeof(pssParams[1]); + isPSS = true; + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + param = &pssParams[2]; + paramLen = sizeof(pssParams[2]); + isPSS = true; + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + param = &pssParams[3]; + paramLen = sizeof(pssParams[3]); + isPSS = true; + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + param = &pssParams[4]; + paramLen = sizeof(pssParams[4]); + isPSS = true; + break; + default: + break; + } + + // Sign the data in blocks + CPPUNIT_ASSERT(rsa->signInit(kp->getPrivateKey(), *m, param, paramLen)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(0, 134))); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134, 289))); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134 + 289))); + CPPUNIT_ASSERT(rsa->signFinal(blockSignature)); + + // Sign the data in one pass + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m, param, paramLen)); + + // If it is not a PSS signature, check if the two signatures match + if (!isPSS) + { + // Check if the two signatures match + CPPUNIT_ASSERT(blockSignature == singlePartSignature); + } + + // Now perform multi-pass verification + CPPUNIT_ASSERT(rsa->verifyInit(kp->getPublicKey(), *m, param, paramLen)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(0, 125))); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125, 247))); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125 + 247))); + CPPUNIT_ASSERT(rsa->verifyFinal(blockSignature)); + + // And single-pass verification + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m, param, paramLen)); + } + + // Test mechanisms that do not perform internal hashing + + // Test PKCS #1 signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 35)); + + // Sign the data + ByteString signature; + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS)); + + // Verify the signature + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS)); + + // Test raw RSA signing + size_t byteSize = *k >> 3; + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, byteSize)); + + // Strip the topmost bit + dataToSign[0] &= 0x7F; + + // Sign the data + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA)); + + // Verify the signature + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA)); + +#ifdef WITH_RAW_PSS + // Test raw (SHA1) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 20)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0]))); + + // Test raw (SHA224) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 28)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1]))); + + // Test raw (SHA256) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 32)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2]))); + + // Test raw (SHA384) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 48)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3]))); + + // Test raw (SHA512) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 64)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4]))); +#endif + + rsa->recycleKeyPair(kp); + } + } +} + +void RSATests::testSignVerifyKnownVector() +{ + // These test vectors were taken from the Crypto++ set of test vectors + // Crypto++ can be downloaded from www.cryptopp.com + +#ifndef WITH_FIPS + RSAPublicKey* pubKey1 = (RSAPublicKey*) rsa->newPublicKey(); + RSAPublicKey* pubKey2 = (RSAPublicKey*) rsa->newPublicKey(); +#endif + RSAPublicKey* pubKey3 = (RSAPublicKey*) rsa->newPublicKey(); +#ifndef WITH_FIPS + RSAPrivateKey* privKey1_1 = (RSAPrivateKey*) rsa->newPrivateKey(); + RSAPrivateKey* privKey1_2 = (RSAPrivateKey*) rsa->newPrivateKey(); + RSAPrivateKey* privKey2_1 = (RSAPrivateKey*) rsa->newPrivateKey(); + RSAPrivateKey* privKey2_2 = (RSAPrivateKey*) rsa->newPrivateKey(); +#endif + RSAPrivateKey* privKey3 = (RSAPrivateKey*) rsa->newPrivateKey(); + +#ifndef WITH_FIPS + // Reconstruct public and private key #1 + ByteString n1 = "0A66791DC6988168DE7AB77419BB7FB0C001C62710270075142942E19A8D8C51D053B3E3782A1DE5DC5AF4EBE99468170114A1DFE67CDC9A9AF55D655620BBAB"; + ByteString e1 = "010001"; + ByteString d1 = "0123C5B61BA36EDB1D3679904199A89EA80C09B9122E1400C09ADCF7784676D01D23356A7D44D6BD8BD50E94BFC723FA87D8862B75177691C11D757692DF8881"; + ByteString p1 = "33D48445C859E52340DE704BCDDA065FBB4058D740BD1D67D29E9C146C11CF61"; + ByteString q1 = "335E8408866B0FD38DC7002D3F972C67389A65D5D8306566D5C4F2A5AA52628B"; + ByteString dp11 = "045EC90071525325D3D46DB79695E9AFACC4523964360E02B119BAA366316241"; + ByteString dq11 = "15EB327360C7B60D12E5E2D16BDCD97981D17FBA6B70DB13B20B436E24EADA59"; + ByteString pq1 = "2CA6366D72781DFA24D34A9A24CBC2AE927A9958AF426563FF63FB11658A461D"; + + pubKey1->setN(n1); + pubKey1->setE(e1); + privKey1_1->setN(n1); + privKey1_1->setE(e1); + privKey1_1->setD(d1); + privKey1_1->setP(p1); + privKey1_1->setQ(q1); + privKey1_1->setDP1(dp11); + privKey1_1->setDQ1(dq11); + privKey1_1->setPQ(pq1); + + // The same key but without CRT factors + privKey1_2->setN(n1); + privKey1_2->setE(e1); + privKey1_2->setD(d1); + + // Reconstruct public and private key #2 + ByteString n2 = "A885B6F851A8079AB8A281DB0297148511EE0D8C07C0D4AE6D6FED461488E0D41E3FF8F281B06A3240B5007A5C2AB4FB6BE8AF88F119DB998368DDDC9710ABED"; + ByteString e2 = "010001"; + ByteString d2 = "2B259D2CA3DF851EE891F6F4678BDDFD9A131C95D3305C63D2723B4A5B9C960F5EC8BB7DCDDBEBD8B6A38767D64AD451E9383E0891E4EE7506100481F2B49323"; + ByteString p2 = "D7103CD676E39824E2BE50B8E6533FE7CB7484348E283802AD2B8D00C80D19DF"; + ByteString q2 = "C89996DC169CEB3F227958275968804D4BE9FC4012C3219662F1A438C9950BB3"; + ByteString dp12 = "5D8EA4C8AF83A70634D5920C3DB66D908AC3AF57A597FD75BC9BBB856181C185"; + ByteString dq12 = "C598E54DAEC8ABC1E907769A6C2BD01653ED0C9960E1EDB7E186FDA922883A99"; + ByteString pq2 = "7C6F27B5B51B78AD80FB36E700990CF307866F2943124CBD93D97C137794C104"; + + pubKey2->setN(n2); + pubKey2->setE(e2); + privKey2_1->setN(n2); + privKey2_1->setE(e2); + privKey2_1->setD(d2); + privKey2_1->setP(p2); + privKey2_1->setQ(q2); + privKey2_1->setDP1(dp12); + privKey2_1->setDQ1(dq12); + privKey2_1->setPQ(pq2); + + // The same key but without CRT factors + privKey2_2->setN(n2); + privKey2_2->setE(e2); + privKey2_2->setD(d2); +#endif + + ByteString n3 = "A8D68ACD413C5E195D5EF04E1B4FAAF242365CB450196755E92E1215BA59802AAFBADBF2564DD550956ABB54F8B1C917844E5F36195D1088C600E07CADA5C080EDE679F50B3DE32CF4026E514542495C54B1903768791AAE9E36F082CD38E941ADA89BAECADA61AB0DD37AD536BCB0A0946271594836E92AB5517301D45176B5"; + ByteString e3 = "03"; + ByteString d3 = "1C23C1CCE034BA598F8FD2B7AF37F1D30B090F7362AEE68E5187ADAE49B9955C729F24A863B7A38D6E3C748E2972F6D940B7BA89043A2D6C2100256A1CF0F56A8CD35FC6EE205244876642F6F9C3820A3D9D2C8921DF7D82AAADCAF2D7334D398931DDBBA553190B3A416099F3AA07FD5B26214645A828419E122CFB857AD73B"; + ByteString p3 = "C107a2fe924b76e206cb9bc4af2ab7008547c00846bf6d0680b3eac3ebcbd0c7fd7a54c2b9899b08f80cde1d3691eaaa2816b1eb11822d6be7beaf4e30977c49"; + ByteString q3 = "DFEA984CE4307EAFC0D140C2BB82861E5DBAC4F8567CBC981D70440DD639492079031486315E305EB83E591C4A2E96064966F7C894C3CA351925B5CE82D8EF0D"; + + pubKey3->setN(n3); + pubKey3->setE(e3); + privKey3->setN(n3); + privKey3->setE(e3); + privKey3->setD(d3); + privKey3->setP(p3); + privKey3->setQ(q3); + +#ifndef WITH_FIPS + // Test with key #1 + const char* testValue1 = "Everyone gets Friday off."; + + ByteString dataToSign1((const unsigned char*) testValue1, strlen(testValue1)); + + ByteString expectedSignature1 = "0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81"; + ByteString signature1_1; + ByteString signature1_2; + + CPPUNIT_ASSERT(rsa->signInit(privKey1_1, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1)); + CPPUNIT_ASSERT(rsa->signFinal(signature1_1)); + +#ifndef WITH_BOTAN + CPPUNIT_ASSERT(rsa->signInit(privKey1_2, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1)); + CPPUNIT_ASSERT(rsa->signFinal(signature1_2)); + + CPPUNIT_ASSERT(signature1_1 == signature1_2); +#endif + CPPUNIT_ASSERT(signature1_1 == expectedSignature1); + + CPPUNIT_ASSERT(rsa->verifyInit(pubKey1, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign1)); + CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature1)); + + // Test with key #2 + const char* testValue2 = "test"; + + ByteString dataToSign2((const unsigned char*) testValue2, strlen(testValue2)); + + ByteString expectedSignature2 = "A7E00CE4391F914D82158D9B732759808E25A1C6383FE87A5199157650D4296CF612E9FF809E686A0AF328238306E79965F6D0138138829D9A1A22764306F6CE"; + ByteString signature2_1; + ByteString signature2_2; + + CPPUNIT_ASSERT(rsa->signInit(privKey2_1, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2)); + CPPUNIT_ASSERT(rsa->signFinal(signature2_1)); + +#ifndef WITH_BOTAN + CPPUNIT_ASSERT(rsa->signInit(privKey2_2, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2)); + CPPUNIT_ASSERT(rsa->signFinal(signature2_2)); + + CPPUNIT_ASSERT(signature2_1 == signature2_2); +#endif + CPPUNIT_ASSERT(signature2_1 == expectedSignature2); + + CPPUNIT_ASSERT(rsa->verifyInit(pubKey2, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign2)); + CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature2)); +#endif + + // Test with key #3 + ByteString dataToSign3 = "D73829497CDDBE41B705FAAC50E7899FDB5A38BF3A459E536357029E64F8796BA47F4FE96BA5A8B9A4396746E2164F55A25368DDD0B9A5188C7AC3DA2D1F742286C3BDEE697F9D546A25EFCFE53191D743FCC6B47833D993D08804DAECA78FB9076C3C017F53E33A90305AF06220974D46BF19ED3C9B84EDBAE98B45A8771258"; + ByteString expectedSignature3 = "175015BDA50ABE0FA7D39A8353885CA01BE3A7E7FCC55045744111362EE1914473A48DC537D956294B9E20A1EF661D58537ACDC8DE908FA050630FCC272E6D001045E6FDEED2D10531C8603334C2E8DB39E73E6D9665EE1343F9E4198302D2201B44E8E8D06B3EF49CEE6197582163A8490089CA654C0012FCE1BA6511089750"; + ByteString signature3; + + CPPUNIT_ASSERT(rsa->signInit(privKey3, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign3)); + CPPUNIT_ASSERT(rsa->signFinal(signature3)); + + CPPUNIT_ASSERT(signature3 == expectedSignature3); + + CPPUNIT_ASSERT(rsa->verifyInit(pubKey3, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign3)); + CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature3)); + +#ifndef WITH_FIPS + rsa->recyclePublicKey(pubKey1); + rsa->recyclePublicKey(pubKey2); +#endif + rsa->recyclePublicKey(pubKey3); +#ifndef WITH_FIPS + rsa->recyclePrivateKey(privKey1_1); + rsa->recyclePrivateKey(privKey1_2); + rsa->recyclePrivateKey(privKey2_1); + rsa->recyclePrivateKey(privKey2_2); +#endif + rsa->recyclePrivateKey(privKey3); +} + +void RSATests::testEncryptDecrypt() +{ + AsymmetricKeyPair* kp; + RSAParameters p; + + // Public exponents to test + std::vector<ByteString> exponents; + exponents.push_back("010001"); + exponents.push_back("03"); + exponents.push_back("0B"); + exponents.push_back("11"); + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + keySizes.push_back(1280); + keySizes.push_back(2048); + //keySizes.push_back(4096); + + // Paddings to test + std::vector<AsymMech::Type> paddings; + paddings.push_back(AsymMech::RSA_PKCS); + paddings.push_back(AsymMech::RSA_PKCS_OAEP); + paddings.push_back(AsymMech::RSA); + + for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++) + { + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + p.setE(*e); + p.setBitLength(*k); + + // Generate key-pair + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + + RNG* rng = CryptoFactory::i()->getRNG(); + + for (std::vector<AsymMech::Type>::iterator pad = paddings.begin(); pad != paddings.end(); pad++) + { + // Generate some test data to encrypt based on the selected padding + ByteString testData; + + if (*pad == AsymMech::RSA_PKCS) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 12)); + } + else if (*pad == AsymMech::RSA_PKCS_OAEP) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 42)); + } + else if (*pad == AsymMech::RSA) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, *k >> 3)); + testData[0] &= 0x0F; + } + else + { + CPPUNIT_ASSERT(true == false); + } + + // Encrypt the data + ByteString encryptedData; + + CPPUNIT_ASSERT(rsa->encrypt(kp->getPublicKey(), testData, encryptedData, *pad)); + + // The encrypted data length should equal the modulus length + CPPUNIT_ASSERT(encryptedData.size() == (*k >> 3)); + CPPUNIT_ASSERT(encryptedData != testData); + + // Now decrypt the data + ByteString decryptedData; + + CPPUNIT_ASSERT(rsa->decrypt(kp->getPrivateKey(), encryptedData, decryptedData, *pad)); + + // Check that the data was properly decrypted + CPPUNIT_ASSERT(decryptedData == testData); + } + + rsa->recycleKeyPair(kp); + } + } +} + diff --git a/SoftHSMv2/src/lib/crypto/test/RSATests.h b/SoftHSMv2/src/lib/crypto/test/RSATests.h new file mode 100644 index 0000000..ca5c86d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RSATests.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + RSATests.h + + Contains test cases to test the RSA class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RSATESTS_H +#define _SOFTHSM_V2_RSATESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class RSATests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(RSATests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST(testEncryptDecrypt); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + void testEncryptDecrypt(); + + void setUp(); + void tearDown(); + +private: + // RSA instance + AsymmetricAlgorithm* rsa; +}; + +#endif // !_SOFTHSM_V2_RSATESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/chisq.c b/SoftHSMv2/src/lib/crypto/test/chisq.c new file mode 100644 index 0000000..3fe4f66 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/chisq.c @@ -0,0 +1,144 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* + + Compute probability of measured Chi Square value. + + This code was developed by Gary Perlman of the Wang + Institute (full citation below) and has been minimally + modified for use in this program. + +*/ + +#include <math.h> + +/*HEADER + Module: z.c + Purpose: compute approximations to normal z distribution probabilities + Programmer: Gary Perlman + Organization: Wang Institute, Tyngsboro, MA 01879 + Copyright: none + Tabstops: 4 +*/ + +#define Z_MAX 6.0 /* maximum meaningful z value */ + +/*FUNCTION poz: probability of normal z value */ +/*ALGORITHM + Adapted from a polynomial approximation in: + Ibbetson D, Algorithm 209 + Collected Algorithms of the CACM 1963 p. 616 + Note: + This routine has six digit accuracy, so it is only useful for absolute + z values < 6. For z values >= to 6.0, poz() returns 0.0. +*/ +static double /*VAR returns cumulative probability from -oo to z */ +poz(const double z) /*VAR normal z value */ +{ + double y, x, w; + + if (z == 0.0) { + x = 0.0; + } else { + y = 0.5 * fabs(z); + if (y >= (Z_MAX * 0.5)) { + x = 1.0; + } else if (y < 1.0) { + w = y * y; + x = ((((((((0.000124818987 * w + -0.001075204047) * w +0.005198775019) * w + -0.019198292004) * w +0.059054035642) * w + -0.151968751364) * w +0.319152932694) * w + -0.531923007300) * w +0.797884560593) * y * 2.0; + } else { + y -= 2.0; + x = (((((((((((((-0.000045255659 * y + +0.000152529290) * y -0.000019538132) * y + -0.000676904986) * y +0.001390604284) * y + -0.000794620820) * y -0.002034254874) * y + +0.006549791214) * y -0.010557625006) * y + +0.011630447319) * y -0.009279453341) * y + +0.005353579108) * y -0.002141268741) * y + +0.000535310849) * y +0.999936657524; + } + } + return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5)); +} + +/* + Module: chisq.c + Purpose: compute approximations to chisquare distribution probabilities + Contents: pochisq() + Uses: poz() in z.c (Algorithm 209) + Programmer: Gary Perlman + Organization: Wang Institute, Tyngsboro, MA 01879 + Copyright: none + Tabstops: 4 +*/ + +#define LOG_SQRT_PI 0.5723649429247000870717135 /* log (sqrt (pi)) */ +#define I_SQRT_PI 0.5641895835477562869480795 /* 1 / sqrt (pi) */ +#define BIGX 20.0 /* max value to represent exp (x) */ +#define ex(x) (((x) < -BIGX) ? 0.0 : exp(x)) + +/*FUNCTION pochisq: probability of chi sqaure value */ +/*ALGORITHM Compute probability of chi square value. + Adapted from: + Hill, I. D. and Pike, M. C. Algorithm 299 + Collected Algorithms for the CACM 1967 p. 243 + Updated for rounding errors based on remark in + ACM TOMS June 1985, page 185 +*/ + +double pochisq( + const double ax, /* obtained chi-square value */ + const int df /* degrees of freedom */ + ) +{ + double x = ax; + double a, y, s; + double e, c, z; + int even; /* true if df is an even number */ + + if (x <= 0.0 || df < 1) { + return 1.0; + } + + a = 0.5 * x; + even = (2 * (df / 2)) == df; + y = 0.0; + if (df > 1) { + y = ex(-a); + } + s = (even ? y : (2.0 * poz(-sqrt(x)))); + if (df > 2) { + x = 0.5 * (df - 1.0); + z = (even ? 1.0 : 0.5); + if (a > BIGX) { + e = (even ? 0.0 : LOG_SQRT_PI); + c = log(a); + while (z <= x) { + e = log(z) + e; + s += ex(c * z - a - e); + z += 1.0; + } + return (s); + } else { + e = (even ? 1.0 : (I_SQRT_PI / sqrt(a))); + c = 0.0; + while (z <= x) { + e = e * (a / z); + c = c + e; + z += 1.0; + } + return (c * y + s); + } + } else { + return s; + } +} diff --git a/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp b/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp new file mode 100644 index 0000000..2fc7b8f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + cryptotest.cpp + + The main test executor for tests on the cryptographic functions in SoftHSM v2 + *****************************************************************************/ + +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> +#include <cppunit/TestResult.h> +#include <cppunit/TestResultCollector.h> +#include <cppunit/XmlOutputter.h> +#include <fstream> + +#include "config.h" +#include "MutexFactory.h" +#include "SecureMemoryRegistry.h" + +#if defined(WITH_OPENSSL) +#include "OSSLCryptoFactory.h" +#else +#include "BotanCryptoFactory.h" +#endif + +// Initialise the one-and-only instance +#ifdef HAVE_CXX11 + +std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr); +std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr); +#if defined(WITH_OPENSSL) +std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr); +#else +std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr); +#endif + +#else + +std::auto_ptr<MutexFactory> MutexFactory::instance(NULL); +std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL); +#if defined(WITH_OPENSSL) +std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL); +#else +std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL); +#endif + +#endif + +int main(int /*argc*/, char** /*argv*/) +{ + CppUnit::TestResult controller; + CppUnit::TestResultCollector result; + CppUnit::TextUi::TestRunner runner; + controller.addListener(&result); + CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); + + runner.addTest(registry.makeTest()); + runner.run(controller); + + std::ofstream xmlFileOut("test-results.xml"); + CppUnit::XmlOutputter xmlOut(&result, xmlFileOut); + xmlOut.write(); + + CryptoFactory::reset(); + + return result.wasSuccessful() ? 0 : 1; +} diff --git a/SoftHSMv2/src/lib/crypto/test/ent.c b/SoftHSMv2/src/lib/crypto/test/ent.c new file mode 100644 index 0000000..b255405 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ent.c @@ -0,0 +1,110 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* + ENT -- Entropy calculation and analysis of putative + random sequences. + + Designed and implemented by John "Random" Walker in May 1985. + + Multiple analyses of random sequences added in December 1985. + + Bit stream analysis added in September 1997. + + Terse mode output, getopt() command line processing, + optional stdin input, and HTML documentation added in + October 1998. + + Documentation for the -t (terse output) option added + in July 2006. + + Replaced table look-up for chi square to probability + conversion with algorithmic computation in January 2008. + + For additional information and the latest version, + see http://www.fourmilab.ch/random/ + +*/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <math.h> +#ifdef _WIN32 +#include <fcntl.h> +#include <io.h> +#else +#include <unistd.h> +#endif + +#include "iso8859.h" +#include "randtest.h" + +#define UPDATE "January 28th, 2008" + +#define FALSE 0 +#define TRUE 1 + +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 +#endif + +extern double pochisq(const double ax, const int df); + +/* Main program */ + +void doEnt +( + unsigned char* data, + size_t len, + double* pEntropy, + double* pChiProbability, + double* pArithMean, + double* pMontePi, + double* pSerialCorrelation +) +{ + size_t s; + long ccount[256]; /* Bins to count occurrences of values */ + double montepi, chip, + scc, ent, mean, chisq; + + /* Initialise for calculations */ + + rt_init(FALSE); + + /* Scan input file and count character occurrences */ + + for (s = 0; s < len; s++) + { + unsigned char ocb = data[s]; + + ccount[ocb]++; /* Update counter for this bin */ + rt_add(&ocb, 1); + } + + /* Complete calculation and return sequence metrics */ + + rt_end(&ent, &chisq, &mean, &montepi, &scc); + + /* Calculate probability of observed distribution occurring from + the results of the Chi-Square test */ + + chip = pochisq(chisq, 255); + + /* Print bin counts if requested */ + + /* Return calculated results */ + + *pEntropy = ent; + *pChiProbability = chip; + *pArithMean = mean; + *pMontePi = montepi; + *pSerialCorrelation = scc; +} diff --git a/SoftHSMv2/src/lib/crypto/test/ent.h b/SoftHSMv2/src/lib/crypto/test/ent.h new file mode 100644 index 0000000..5958888 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ent.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010 SURFnet bv + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************************************************************** + ent.h + + Header file to give access to the modified ent.c implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ENT_H +#define _SOFTHSM_V2_ENT_H + +#if defined(__cplusplus) +extern "C" { +#endif + +void doEnt +( + unsigned char* data, + size_t len, + double* pEntropy, + double* pChiProbability, + double* pArithMean, + double* pMontePi, + double* pSerialCorrelation +); + +#if defined(__cplusplus) +} +#endif + +#endif // !_SOFTHSM_V2_ENT_H + diff --git a/SoftHSMv2/src/lib/crypto/test/iso8859.c b/SoftHSMv2/src/lib/crypto/test/iso8859.c new file mode 100644 index 0000000..bed7244 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/iso8859.c @@ -0,0 +1,25 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* ISO 8859/1 Latin-1 alphabetic and upper and lower case bit vector tables. */ + +/* LINTLIBRARY */ + +unsigned char isoalpha[32] = { + 0,0,0,0,0,0,0,0,127,255,255,224,127,255,255,224,0,0,0,0,0,0,0,0,255,255, + 254,255,255,255,254,255 +}; + +unsigned char isoupper[32] = { + 0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,0,255,255,254,254, + 0,0,0,0 +}; + +unsigned char isolower[32] = { + 0,0,0,0,0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,1,255,255, + 254,255 +}; diff --git a/SoftHSMv2/src/lib/crypto/test/iso8859.h b/SoftHSMv2/src/lib/crypto/test/iso8859.h new file mode 100644 index 0000000..7462f15 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/iso8859.h @@ -0,0 +1,23 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* ISO 8859/1 Latin-1 "ctype" macro replacements. */ + +extern unsigned char isoalpha[32], isoupper[32], isolower[32]; + +#define isISOspace(x) ((isascii(((unsigned char) (x))) && isspace(((unsigned char) (x)))) || ((x) == 0xA0)) +#define isISOalpha(x) ((isoalpha[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0) +#define isISOupper(x) ((isoupper[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0) +#define isISOlower(x) ((isolower[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0) +#define isISOprint(x) ((((x) >= ' ') && ((x) <= '~')) || ((x) >= 0xA0)) +#define toISOupper(x) (isISOlower(x) ? (isascii(((unsigned char) (x))) ? \ + toupper(x) : (((((unsigned char) (x)) != 0xDF) && \ + (((unsigned char) (x)) != 0xFF)) ? \ + (((unsigned char) (x)) - 0x20) : (x))) : (x)) +#define toISOlower(x) (isISOupper(x) ? (isascii(((unsigned char) (x))) ? \ + tolower(x) : (((unsigned char) (x)) + 0x20)) \ + : (x)) diff --git a/SoftHSMv2/src/lib/crypto/test/randtest.c b/SoftHSMv2/src/lib/crypto/test/randtest.c new file mode 100644 index 0000000..5a54737 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/randtest.c @@ -0,0 +1,190 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* + + Apply various randomness tests to a stream of bytes + + by John Walker -- September 1996 + http://www.fourmilab.ch/ + +*/ + +#include <math.h> + +#define FALSE 0 +#define TRUE 1 + +#define log2of10 3.32192809488736234787 + +static int binary = FALSE; /* Treat input as a bitstream */ + +static long ccount[256], /* Bins to count occurrences of values */ + totalc = 0; /* Total bytes counted */ +static double prob[256]; /* Probabilities per bin for entropy */ + +/* RT_LOG2 -- Calculate log to the base 2 */ + +static double rt_log2(double x) +{ + return log2of10 * log10(x); +} + +#define MONTEN 6 /* Bytes used as Monte Carlo + co-ordinates. This should be no more + bits than the mantissa of your + "double" floating point type. */ + +static int mp, sccfirst; +static unsigned int monte[MONTEN]; +static long inmont, mcount; +static double cexp, incirc, montex, montey, montepi, + scc, sccun, sccu0, scclast, scct1, scct2, scct3, + ent, chisq, datasum; + +/* RT_INIT -- Initialise random test counters. */ + +void rt_init(int binmode) +{ + int i; + + binary = binmode; /* Set binary / byte mode */ + + /* Initialise for calculations */ + + ent = 0.0; /* Clear entropy accumulator */ + chisq = 0.0; /* Clear Chi-Square */ + datasum = 0.0; /* Clear sum of bytes for arithmetic mean */ + + mp = 0; /* Reset Monte Carlo accumulator pointer */ + mcount = 0; /* Clear Monte Carlo tries */ + inmont = 0; /* Clear Monte Carlo inside count */ + incirc = 65535.0 * 65535.0;/* In-circle distance for Monte Carlo */ + + sccfirst = TRUE; /* Mark first time for serial correlation */ + scct1 = scct2 = scct3 = 0.0; /* Clear serial correlation terms */ + + incirc = pow(pow(256.0, (double) (MONTEN / 2)) - 1, 2.0); + + for (i = 0; i < 256; i++) { + ccount[i] = 0; + } + totalc = 0; +} + +/* RT_ADD -- Add one or more bytes to accumulation. */ + +void rt_add(void *buf, int bufl) +{ + unsigned char *bp = (unsigned char *)buf; + int oc, c, bean; + + while (bean = 0, (bufl-- > 0)) { + oc = *bp++; + + do { + if (binary) { + c = !!(oc & 0x80); + } else { + c = oc; + } + ccount[c]++; /* Update counter for this bin */ + totalc++; + + /* Update inside / outside circle counts for Monte Carlo + computation of PI */ + + if (bean == 0) { + monte[mp++] = oc; /* Save character for Monte Carlo */ + if (mp >= MONTEN) { /* Calculate every MONTEN character */ + int mj; + + mp = 0; + mcount++; + montex = montey = 0; + for (mj = 0; mj < MONTEN / 2; mj++) { + montex = (montex * 256.0) + monte[mj]; + montey = (montey * 256.0) + monte[(MONTEN / 2) + mj]; + } + if ((montex * montex + montey * montey) <= incirc) { + inmont++; + } + } + } + + /* Update calculation of serial correlation coefficient */ + + sccun = c; + if (sccfirst) { + sccfirst = FALSE; + scclast = 0; + sccu0 = sccun; + } else { + scct1 = scct1 + scclast * sccun; + } + scct2 = scct2 + sccun; + scct3 = scct3 + (sccun * sccun); + scclast = sccun; + oc <<= 1; + } while (binary && (++bean < 8)); + } +} + +/* RT_END -- Complete calculation and return results. */ + +void rt_end(double *r_ent, double *r_chisq, double *r_mean, + double *r_montepicalc, double *r_scc) +{ + int i; + + /* Complete calculation of serial correlation coefficient */ + + scct1 = scct1 + scclast * sccu0; + scct2 = scct2 * scct2; + scc = totalc * scct3 - scct2; + if (scc == 0.0) { + scc = -100000; + } else { + scc = (totalc * scct1 - scct2) / scc; + } + + /* Scan bins and calculate probability for each bin and + Chi-Square distribution. The probability will be reused + in the entropy calculation below. While we're at it, + we sum of all the data which will be used to compute the + mean. */ + + cexp = totalc / (binary ? 2.0 : 256.0); /* Expected count per bin */ + for (i = 0; i < (binary ? 2 : 256); i++) { + double a = ccount[i] - cexp;; + + prob[i] = ((double) ccount[i]) / totalc; + chisq += (a * a) / cexp; + datasum += ((double) i) * ccount[i]; + } + + /* Calculate entropy */ + + for (i = 0; i < (binary ? 2 : 256); i++) { + if (prob[i] > 0.0) { + ent += prob[i] * rt_log2(1 / prob[i]); + } + } + + /* Calculate Monte Carlo value for PI from percentage of hits + within the circle */ + + montepi = 4.0 * (((double) inmont) / mcount); + + /* Return results through arguments */ + + *r_ent = ent; + *r_chisq = chisq; + *r_mean = datasum / totalc; + *r_montepicalc = montepi; + *r_scc = scc; +} diff --git a/SoftHSMv2/src/lib/crypto/test/randtest.h b/SoftHSMv2/src/lib/crypto/test/randtest.h new file mode 100644 index 0000000..53bef35 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/randtest.h @@ -0,0 +1,13 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* Random test function prototypes */ + +extern void rt_init(int binmode); +extern void rt_add(void *buf, int bufl); +extern void rt_end(double *r_ent, double *r_chisq, double *r_mean, + double *r_montepicalc, double *r_scc); |