• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2017, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 /* test_fips exercises various cryptographic primitives for demonstration
16  * purposes in the validation process only. */
17 
18 #include <stdio.h>
19 
20 #include <openssl/aead.h>
21 #include <openssl/aes.h>
22 #include <openssl/bn.h>
23 #include <openssl/crypto.h>
24 #include <openssl/ctrdrbg.h>
25 #include <openssl/des.h>
26 #include <openssl/dh.h>
27 #include <openssl/ec_key.h>
28 #include <openssl/ecdsa.h>
29 #include <openssl/err.h>
30 #include <openssl/hkdf.h>
31 #include <openssl/hmac.h>
32 #include <openssl/nid.h>
33 #include <openssl/rsa.h>
34 #include <openssl/sha.h>
35 
36 #include "../../crypto/fipsmodule/rand/internal.h"
37 #include "../../crypto/fipsmodule/tls/internal.h"
38 #include "../../crypto/internal.h"
39 
40 
hexdump(const void * a,size_t len)41 static void hexdump(const void *a, size_t len) {
42   const unsigned char *in = (const unsigned char *)a;
43   for (size_t i = 0; i < len; i++) {
44     printf("%02x", in[i]);
45   }
46 
47   printf("\n");
48 }
49 
main(int argc,char ** argv)50 int main(int argc, char **argv) {
51   CRYPTO_library_init();
52 
53   const uint32_t module_version = FIPS_version();
54   if (module_version == 0) {
55     printf("No module version set\n");
56     goto err;
57   }
58   printf("Module: '%s', version: %" PRIu32 "\n", FIPS_module_name(),
59          module_version);
60 
61   static const uint8_t kAESKey[16] = "BoringCrypto Key";
62   static const uint8_t kPlaintext[64] =
63       "BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!";
64   static const DES_cblock kDESKey1 = {"BCMDESK1"};
65   static const DES_cblock kDESKey2 = {"BCMDESK2"};
66   static const DES_cblock kDESKey3 = {"BCMDESK3"};
67   static const DES_cblock kDESIV = {"BCMDESIV"};
68   static const uint8_t kPlaintextSHA256[32] = {
69       0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb,
70       0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb,
71       0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, 0x0f};
72   const uint8_t kDRBGEntropy[48] =
73       "DBRG Initial Entropy                            ";
74   const uint8_t kDRBGPersonalization[18] = "BCMPersonalization";
75   const uint8_t kDRBGAD[16] = "BCM DRBG AD     ";
76   const uint8_t kDRBGEntropy2[48] =
77       "DBRG Reseed Entropy                             ";
78 
79   AES_KEY aes_key;
80   uint8_t aes_iv[16];
81   uint8_t output[256];
82 
83   /* AES-CBC Encryption */
84   memset(aes_iv, 0, sizeof(aes_iv));
85   if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
86     printf("AES_set_encrypt_key failed\n");
87     goto err;
88   }
89 
90   printf("About to AES-CBC encrypt ");
91   hexdump(kPlaintext, sizeof(kPlaintext));
92   AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv,
93                   AES_ENCRYPT);
94   printf("  got ");
95   hexdump(output, sizeof(kPlaintext));
96 
97   /* AES-CBC Decryption */
98   memset(aes_iv, 0, sizeof(aes_iv));
99   if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
100     printf("AES decrypt failed\n");
101     goto err;
102   }
103   printf("About to AES-CBC decrypt ");
104   hexdump(output, sizeof(kPlaintext));
105   AES_cbc_encrypt(output, output, sizeof(kPlaintext), &aes_key, aes_iv,
106                   AES_DECRYPT);
107   printf("  got ");
108   hexdump(output, sizeof(kPlaintext));
109 
110   size_t out_len;
111   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
112   OPENSSL_memset(nonce, 0, sizeof(nonce));
113   EVP_AEAD_CTX aead_ctx;
114   if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
115                          sizeof(kAESKey), 0, NULL)) {
116     printf("EVP_AEAD_CTX_init failed\n");
117     goto err;
118   }
119 
120   /* AES-GCM Encryption */
121   printf("About to AES-GCM seal ");
122   hexdump(output, sizeof(kPlaintext));
123   if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
124                          EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
125                          kPlaintext, sizeof(kPlaintext), NULL, 0)) {
126     printf("AES-GCM encrypt failed\n");
127     goto err;
128   }
129   printf("  got ");
130   hexdump(output, out_len);
131 
132   /* AES-GCM Decryption */
133   printf("About to AES-GCM open ");
134   hexdump(output, out_len);
135   if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
136                          EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
137                          output, out_len, NULL, 0)) {
138     printf("AES-GCM decrypt failed\n");
139     goto err;
140   }
141   printf("  got ");
142   hexdump(output, out_len);
143 
144   EVP_AEAD_CTX_cleanup(&aead_ctx);
145 
146   DES_key_schedule des1, des2, des3;
147   DES_cblock des_iv;
148   DES_set_key(&kDESKey1, &des1);
149   DES_set_key(&kDESKey2, &des2);
150   DES_set_key(&kDESKey3, &des3);
151 
152   /* 3DES Encryption */
153   memcpy(&des_iv, &kDESIV, sizeof(des_iv));
154   printf("About to 3DES-CBC encrypt ");
155   hexdump(kPlaintext, sizeof(kPlaintext));
156   DES_ede3_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &des1, &des2,
157                        &des3, &des_iv, DES_ENCRYPT);
158   printf("  got ");
159   hexdump(output, sizeof(kPlaintext));
160 
161   /* 3DES Decryption */
162   memcpy(&des_iv, &kDESIV, sizeof(des_iv));
163   printf("About to 3DES-CBC decrypt ");
164   hexdump(kPlaintext, sizeof(kPlaintext));
165   DES_ede3_cbc_encrypt(output, output, sizeof(kPlaintext), &des1,
166                        &des2, &des3, &des_iv, DES_DECRYPT);
167   printf("  got ");
168   hexdump(output, sizeof(kPlaintext));
169 
170   /* SHA-1 */
171   printf("About to SHA-1 hash ");
172   hexdump(kPlaintext, sizeof(kPlaintext));
173   SHA1(kPlaintext, sizeof(kPlaintext), output);
174   printf("  got ");
175   hexdump(output, SHA_DIGEST_LENGTH);
176 
177   /* SHA-256 */
178   printf("About to SHA-256 hash ");
179   hexdump(kPlaintext, sizeof(kPlaintext));
180   SHA256(kPlaintext, sizeof(kPlaintext), output);
181   printf("  got ");
182   hexdump(output, SHA256_DIGEST_LENGTH);
183 
184   /* SHA-512 */
185   printf("About to SHA-512 hash ");
186   hexdump(kPlaintext, sizeof(kPlaintext));
187   SHA512(kPlaintext, sizeof(kPlaintext), output);
188   printf("  got ");
189   hexdump(output, SHA512_DIGEST_LENGTH);
190 
191   RSA *rsa_key = RSA_new();
192   printf("About to generate RSA key\n");
193   if (!RSA_generate_key_fips(rsa_key, 2048, NULL)) {
194     printf("RSA_generate_key_fips failed\n");
195     goto err;
196   }
197 
198   /* RSA Sign */
199   unsigned sig_len;
200   printf("About to RSA sign ");
201   hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256));
202   if (!RSA_sign(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), output,
203                 &sig_len, rsa_key)) {
204     printf("RSA Sign failed\n");
205     goto err;
206   }
207   printf("  got ");
208   hexdump(output, sig_len);
209 
210   /* RSA Verify */
211   printf("About to RSA verify ");
212   hexdump(output, sig_len);
213   if (!RSA_verify(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256),
214                   output, sig_len, rsa_key)) {
215     printf("RSA Verify failed.\n");
216     goto err;
217   }
218 
219   RSA_free(rsa_key);
220 
221   /* Generating a key with a null output parameter. */
222   printf("About to generate RSA key with null output\n");
223   if (!RSA_generate_key_fips(NULL, 2048, NULL)) {
224     printf("RSA_generate_key_fips failed with null output parameter\n");
225     ERR_clear_error();
226   } else {
227     printf(
228         "RSA_generate_key_fips unexpectedly succeeded with null output "
229         "parameter\n");
230     goto err;
231   }
232 
233   EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
234   if (ec_key == NULL) {
235     printf("invalid ECDSA key\n");
236     goto err;
237   }
238 
239   printf("About to generate P-256 key\n");
240   if (!EC_KEY_generate_key_fips(ec_key)) {
241     printf("EC_KEY_generate_key_fips failed\n");
242     goto err;
243   }
244 
245   /* Primitive Z Computation */
246   const EC_GROUP *const ec_group = EC_KEY_get0_group(ec_key);
247   EC_POINT *z_point = EC_POINT_new(ec_group);
248   uint8_t z_result[65];
249   printf("About to compute key-agreement Z with P-256:\n");
250   if (!EC_POINT_mul(ec_group, z_point, NULL, EC_KEY_get0_public_key(ec_key),
251                     EC_KEY_get0_private_key(ec_key), NULL) ||
252       EC_POINT_point2oct(ec_group, z_point, POINT_CONVERSION_UNCOMPRESSED,
253                          z_result, sizeof(z_result),
254                          NULL) != sizeof(z_result)) {
255     fprintf(stderr, "EC_POINT_mul failed.\n");
256     goto err;
257   }
258   EC_POINT_free(z_point);
259 
260   printf("  got ");
261   hexdump(z_result, sizeof(z_result));
262 
263   /* ECDSA Sign/Verify PWCT */
264   printf("About to ECDSA sign ");
265   hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256));
266   ECDSA_SIG *sig =
267       ECDSA_do_sign(kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key);
268   if (sig == NULL ||
269       !ECDSA_do_verify(kPlaintextSHA256, sizeof(kPlaintextSHA256), sig,
270                        ec_key)) {
271     printf("ECDSA Sign/Verify PWCT failed.\n");
272     goto err;
273   }
274 
275   ECDSA_SIG_free(sig);
276   EC_KEY_free(ec_key);
277 
278   /* Generating a key with a null output pointer. */
279   printf("About to generate P-256 key with NULL output\n");
280   if (!EC_KEY_generate_key_fips(NULL)) {
281     printf("EC_KEY_generate_key_fips failed with a NULL output pointer.\n");
282     ERR_clear_error();
283   } else {
284     printf(
285         "EC_KEY_generate_key_fips unexpectedly succeeded with a NULL output "
286         "pointer.\n");
287     goto err;
288   }
289 
290   /* ECDSA with an invalid public key. */
291   ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
292   static const uint8_t kNotValidX926[] = {1,2,3,4,5,6};
293   if (!EC_KEY_oct2key(ec_key, kNotValidX926, sizeof(kNotValidX926),
294                       /*ctx=*/NULL)) {
295     printf("Error while parsing invalid ECDSA public key");
296   } else {
297     printf("Unexpected success while parsing invalid ECDSA public key");
298     goto err;
299   }
300   EC_KEY_free(ec_key);
301 
302   /* DBRG */
303   CTR_DRBG_STATE drbg;
304   printf("About to seed CTR-DRBG with ");
305   hexdump(kDRBGEntropy, sizeof(kDRBGEntropy));
306   if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization,
307                      sizeof(kDRBGPersonalization)) ||
308       !CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD,
309                          sizeof(kDRBGAD)) ||
310       !CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) ||
311       !CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD,
312                          sizeof(kDRBGAD))) {
313     printf("DRBG failed\n");
314     goto err;
315   }
316   printf("  generated ");
317   hexdump(output, sizeof(output));
318   CTR_DRBG_clear(&drbg);
319 
320   /* HKDF */
321   printf("About to run HKDF\n");
322   uint8_t hkdf_output[32];
323   if (!HKDF(hkdf_output, sizeof(hkdf_output), EVP_sha256(), kAESKey,
324             sizeof(kAESKey), (const uint8_t *)"salt", 4, kPlaintextSHA256,
325             sizeof(kPlaintextSHA256))) {
326     fprintf(stderr, "HKDF failed.\n");
327     goto err;
328   }
329   printf("  got ");
330   hexdump(hkdf_output, sizeof(hkdf_output));
331 
332   /* TLS v1.0 KDF */
333   printf("About to run TLS v1.0 KDF\n");
334   uint8_t tls10_output[32];
335   if (!CRYPTO_tls1_prf(EVP_md5_sha1(), tls10_output, sizeof(tls10_output),
336                        kAESKey, sizeof(kAESKey), "foo", 3, kPlaintextSHA256,
337                        sizeof(kPlaintextSHA256), kPlaintextSHA256,
338                        sizeof(kPlaintextSHA256))) {
339     fprintf(stderr, "TLS v1.0 KDF failed.\n");
340     goto err;
341   }
342   printf("  got ");
343   hexdump(tls10_output, sizeof(tls10_output));
344 
345   /* TLS v1.2 KDF */
346   printf("About to run TLS v1.2 KDF\n");
347   uint8_t tls12_output[32];
348   if (!CRYPTO_tls1_prf(EVP_sha256(), tls12_output, sizeof(tls12_output),
349                        kAESKey, sizeof(kAESKey), "foo", 3, kPlaintextSHA256,
350                        sizeof(kPlaintextSHA256), kPlaintextSHA256,
351                        sizeof(kPlaintextSHA256))) {
352     fprintf(stderr, "TLS v1.2 KDF failed.\n");
353     goto err;
354   }
355   printf("  got ");
356   hexdump(tls12_output, sizeof(tls12_output));
357 
358   /* TLS v1.3 KDF */
359   printf("About to run TLS v1.3 KDF\n");
360   uint8_t tls13_output[32];
361   if (!CRYPTO_tls13_hkdf_expand_label(
362           tls13_output, sizeof(tls13_output), EVP_sha256(), kAESKey,
363           sizeof(kAESKey), (const uint8_t *)"foo", 3, kPlaintextSHA256,
364           sizeof(kPlaintextSHA256))) {
365     fprintf(stderr, "TLS v1.3 KDF failed.\n");
366     goto err;
367   }
368   printf("  got ");
369   hexdump(tls13_output, sizeof(tls13_output));
370 
371   /* FFDH */
372   printf("About to compute FFDH key-agreement:\n");
373   DH *dh = DH_get_rfc7919_2048();
374   uint8_t dh_result[2048/8];
375   if (!dh ||
376       !DH_generate_key(dh) ||
377       sizeof(dh_result) != DH_size(dh) ||
378       DH_compute_key_padded(dh_result, DH_get0_pub_key(dh), dh) !=
379           sizeof(dh_result)) {
380     fprintf(stderr, "FFDH failed.\n");
381     goto err;
382   }
383   DH_free(dh);
384 
385   printf("  got ");
386   hexdump(dh_result, sizeof(dh_result));
387 
388   printf("PASS\n");
389   return 0;
390 
391 err:
392   printf("FAIL\n");
393   fflush(stdout);
394   abort();
395 }
396