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