1#ifndef CRYPTOPP_DLL_ONLY
2#define CRYPTOPP_DEFAULT_NO_DLL
3#endif
4
5#include "dll.h"
6#include <iostream>
7
8USING_NAMESPACE(CryptoPP)
9USING_NAMESPACE(std)
10
11void FIPS140_SampleApplication()
12{
13	if (!FIPS_140_2_ComplianceEnabled())
14	{
15		cerr << "FIPS 140-2 compliance was turned off at compile time.\n";
16		abort();
17	}
18
19	// check self test status
20	if (GetPowerUpSelfTestStatus() != POWER_UP_SELF_TEST_PASSED)
21	{
22		cerr << "Automatic power-up self test failed.\n";
23		abort();
24	}
25	cout << "0. Automatic power-up self test passed.\n";
26
27	// simulate a power-up self test error
28	SimulatePowerUpSelfTestFailure();
29	try
30	{
31		// trying to use a crypto algorithm after power-up self test error will result in an exception
32		AES::Encryption aes;
33
34		// should not be here
35		cerr << "Use of AES failed to cause an exception after power-up self test error.\n";
36		abort();
37	}
38	catch (SelfTestFailure &e)
39	{
40		cout << "1. Caught expected exception when simulating self test failure. Exception message follows: ";
41		cout << e.what() << endl;
42	}
43
44	// clear the self test error state and redo power-up self test
45	DoDllPowerUpSelfTest();
46	if (GetPowerUpSelfTestStatus() != POWER_UP_SELF_TEST_PASSED)
47	{
48		cerr << "Re-do power-up self test failed.\n";
49		abort();
50	}
51	cout << "2. Re-do power-up self test passed.\n";
52
53	// encrypt and decrypt
54	const byte key[] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
55	const byte iv[] = {0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef};
56	const byte plaintext[] = {	// "Now is the time for all " without tailing 0
57		0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
58		0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
59		0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20};
60	byte ciphertext[24];
61	byte decrypted[24];
62
63	CFB_FIPS_Mode<DES_EDE3>::Encryption encryption_DES_EDE3_CFB;
64	encryption_DES_EDE3_CFB.SetKeyWithIV(key, sizeof(key), iv);
65	encryption_DES_EDE3_CFB.ProcessString(ciphertext, plaintext, 24);
66
67	CFB_FIPS_Mode<DES_EDE3>::Decryption decryption_DES_EDE3_CFB;
68	decryption_DES_EDE3_CFB.SetKeyWithIV(key, sizeof(key), iv);
69	decryption_DES_EDE3_CFB.ProcessString(decrypted, ciphertext, 24);
70
71	if (memcmp(plaintext, decrypted, 24) != 0)
72	{
73		cerr << "DES-EDE3-CFB Encryption/decryption failed.\n";
74		abort();
75	}
76	cout << "3. DES-EDE3-CFB Encryption/decryption succeeded.\n";
77
78	// hash
79	const byte message[] = {'a', 'b', 'c'};
80	const byte expectedDigest[] = {0xA9,0x99,0x3E,0x36,0x47,0x06,0x81,0x6A,0xBA,0x3E,0x25,0x71,0x78,0x50,0xC2,0x6C,0x9C,0xD0,0xD8,0x9D};
81	byte digest[20];
82
83	SHA1 sha;
84	sha.Update(message, 3);
85	sha.Final(digest);
86
87	if (memcmp(digest, expectedDigest, 20) != 0)
88	{
89		cerr << "SHA-1 hash failed.\n";
90		abort();
91	}
92	cout << "4. SHA-1 hash succeeded.\n";
93
94	// create auto-seeded X9.17 RNG object, if available
95#ifdef OS_RNG_AVAILABLE
96	AutoSeededX917RNG<AES> rng;
97#else
98	// this is used to allow this function to compile on platforms that don't have auto-seeded RNGs
99	RandomNumberGenerator &rng(NullRNG());
100#endif
101
102	// generate DSA key
103	DSA::PrivateKey dsaPrivateKey;
104	dsaPrivateKey.GenerateRandomWithKeySize(rng, 1024);
105	DSA::PublicKey dsaPublicKey;
106	dsaPublicKey.AssignFrom(dsaPrivateKey);
107	if (!dsaPrivateKey.Validate(rng, 3) || !dsaPublicKey.Validate(rng, 3))
108	{
109		cerr << "DSA key generation failed.\n";
110		abort();
111	}
112	cout << "5. DSA key generation succeeded.\n";
113
114	// encode DSA key
115	std::string encodedDsaPublicKey, encodedDsaPrivateKey;
116	dsaPublicKey.DEREncode(StringSink(encodedDsaPublicKey).Ref());
117	dsaPrivateKey.DEREncode(StringSink(encodedDsaPrivateKey).Ref());
118
119	// decode DSA key
120	DSA::PrivateKey decodedDsaPrivateKey;
121	decodedDsaPrivateKey.BERDecode(StringStore(encodedDsaPrivateKey).Ref());
122	DSA::PublicKey decodedDsaPublicKey;
123	decodedDsaPublicKey.BERDecode(StringStore(encodedDsaPublicKey).Ref());
124
125	if (!decodedDsaPrivateKey.Validate(rng, 3) || !decodedDsaPublicKey.Validate(rng, 3))
126	{
127		cerr << "DSA key encode/decode failed.\n";
128		abort();
129	}
130	cout << "6. DSA key encode/decode succeeded.\n";
131
132	// sign and verify
133	byte signature[40];
134	DSA::Signer signer(dsaPrivateKey);
135	assert(signer.SignatureLength() == 40);
136	signer.SignMessage(rng, message, 3, signature);
137
138	DSA::Verifier verifier(dsaPublicKey);
139	if (!verifier.VerifyMessage(message, 3, signature, sizeof(signature)))
140	{
141		cerr << "DSA signature and verification failed.\n";
142		abort();
143	}
144	cout << "7. DSA signature and verification succeeded.\n";
145
146
147	// try to verify an invalid signature
148	signature[0] ^= 1;
149	if (verifier.VerifyMessage(message, 3, signature, sizeof(signature)))
150	{
151		cerr << "DSA signature verification failed to detect bad signature.\n";
152		abort();
153	}
154	cout << "8. DSA signature verification successfully detected bad signature.\n";
155
156	// try to use an invalid key length
157	try
158	{
159		ECB_Mode<DES_EDE3>::Encryption encryption_DES_EDE3_ECB;
160		encryption_DES_EDE3_ECB.SetKey(key, 5);
161
162		// should not be here
163		cerr << "DES-EDE3 implementation did not detect use of invalid key length.\n";
164		abort();
165	}
166	catch (InvalidArgument &e)
167	{
168		cout << "9. Caught expected exception when using invalid key length. Exception message follows: ";
169		cout << e.what() << endl;
170	}
171
172	cout << "\nFIPS 140-2 Sample Application completed normally.\n";
173}
174
175#ifdef CRYPTOPP_IMPORTS
176
177static PNew s_pNew = NULL;
178static PDelete s_pDelete = NULL;
179
180extern "C" __declspec(dllexport) void __cdecl SetNewAndDeleteFromCryptoPP(PNew pNew, PDelete pDelete, PSetNewHandler pSetNewHandler)
181{
182	s_pNew = pNew;
183	s_pDelete = pDelete;
184}
185
186void * __cdecl operator new (size_t size)
187{
188	return s_pNew(size);
189}
190
191void __cdecl operator delete (void * p)
192{
193	s_pDelete(p);
194}
195
196#endif
197
198#ifdef CRYPTOPP_DLL_ONLY
199
200int __cdecl main()
201{
202	FIPS140_SampleApplication();
203	return 0;
204}
205
206#endif
207