1 /* Copyright 2017 The BoringSSL Authors
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/bytestring.h>
24 #include <openssl/crypto.h>
25 #include <openssl/ctrdrbg.h>
26 #include <openssl/des.h>
27 #include <openssl/dh.h>
28 #include <openssl/ec_key.h>
29 #include <openssl/ecdsa.h>
30 #include <openssl/err.h>
31 #include <openssl/hkdf.h>
32 #include <openssl/hmac.h>
33 #include <openssl/nid.h>
34 #include <openssl/rsa.h>
35 #include <openssl/sha.h>
36
37 #include "../../crypto/fipsmodule/bcm_interface.h"
38 #include "../../crypto/fipsmodule/rand/internal.h"
39 #include "../../crypto/fipsmodule/tls/internal.h"
40 #include "../../crypto/internal.h"
41
42 OPENSSL_MSVC_PRAGMA(warning(disable : 4295))
43
44 #if defined(BORINGSSL_FIPS)
hexdump(const void * a,size_t len)45 static void hexdump(const void *a, size_t len) {
46 const unsigned char *in = (const unsigned char *)a;
47 for (size_t i = 0; i < len; i++) {
48 printf("%02x", in[i]);
49 }
50
51 printf("\n");
52 }
53 #endif
54
run_test()55 static int run_test() {
56 // Ensure that the output is line-buffered rather than fully buffered. When
57 // some of the tests fail, some of the output can otherwise be lost.
58 setvbuf(stdout, NULL, _IOLBF, 0);
59 setvbuf(stderr, NULL, _IOLBF, 0);
60
61 if (!FIPS_mode()) {
62 printf("Module not in FIPS mode\n");
63 return 0;
64 }
65 printf("Module is in FIPS mode\n");
66
67 const uint32_t module_version = FIPS_version();
68 if (module_version == 0) {
69 printf("No module version set\n");
70 // return 0;
71 }
72 printf("Module: '%s', version: %" PRIu32 " hash:\n", FIPS_module_name(),
73 module_version);
74
75 #if !defined(BORINGSSL_FIPS)
76 // |module_version| will be zero, so the non-FIPS build will never get
77 // this far.
78 printf("Non zero module version in non-FIPS build - should not happen!\n");
79 return 0;
80 #else
81 #if defined(OPENSSL_ASAN)
82 printf("(not available when compiled for ASAN)");
83 #else
84 hexdump(FIPS_module_hash(), SHA256_DIGEST_LENGTH);
85 #endif
86
87 static const uint8_t kAESKey[16] = "BoringCrypto Ky";
88 static const uint8_t kPlaintext[64] =
89 "BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext";
90 static const DES_cblock kDESKey1 = {"BCMDES1"};
91 static const DES_cblock kDESKey2 = {"BCMDES2"};
92 static const DES_cblock kDESKey3 = {"BCMDES3"};
93 static const DES_cblock kDESIV = {"BCMDESI"};
94 static const uint8_t kPlaintextSHA256[32] = {
95 0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb,
96 0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb,
97 0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, 0x0f};
98 const uint8_t kDRBGEntropy[48] =
99 "DBRG Initial Entropy ";
100 const uint8_t kDRBGPersonalization[19] = "BCMPersonalization";
101 const uint8_t kDRBGAD[16] = "BCM DRBG AD ";
102 const uint8_t kDRBGEntropy2[48] =
103 "DBRG Reseed Entropy ";
104
105 AES_KEY aes_key;
106 uint8_t aes_iv[16];
107 uint8_t output[256];
108
109 /* AES-CBC Encryption */
110 memset(aes_iv, 0, sizeof(aes_iv));
111 if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
112 printf("AES_set_encrypt_key failed\n");
113 return 0;
114 }
115
116 printf("About to AES-CBC encrypt ");
117 hexdump(kPlaintext, sizeof(kPlaintext));
118 AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv,
119 AES_ENCRYPT);
120 printf(" got ");
121 hexdump(output, sizeof(kPlaintext));
122
123 /* AES-CBC Decryption */
124 memset(aes_iv, 0, sizeof(aes_iv));
125 if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
126 printf("AES decrypt failed\n");
127 return 0;
128 }
129 printf("About to AES-CBC decrypt ");
130 hexdump(output, sizeof(kPlaintext));
131 AES_cbc_encrypt(output, output, sizeof(kPlaintext), &aes_key, aes_iv,
132 AES_DECRYPT);
133 printf(" got ");
134 hexdump(output, sizeof(kPlaintext));
135
136 size_t out_len;
137 uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
138 OPENSSL_memset(nonce, 0, sizeof(nonce));
139 EVP_AEAD_CTX aead_ctx;
140 if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
141 sizeof(kAESKey), 0, NULL)) {
142 printf("EVP_AEAD_CTX_init failed\n");
143 return 0;
144 }
145
146 /* AES-GCM Encryption */
147 printf("About to AES-GCM seal ");
148 hexdump(output, sizeof(kPlaintext));
149 if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
150 EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
151 kPlaintext, sizeof(kPlaintext), NULL, 0)) {
152 printf("AES-GCM encrypt failed\n");
153 return 0;
154 }
155 printf(" got ");
156 hexdump(output, out_len);
157
158 /* AES-GCM Decryption */
159 printf("About to AES-GCM open ");
160 hexdump(output, out_len);
161 if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
162 EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), output,
163 out_len, NULL, 0)) {
164 printf("AES-GCM decrypt failed\n");
165 return 0;
166 }
167 printf(" got ");
168 hexdump(output, out_len);
169
170 EVP_AEAD_CTX_cleanup(&aead_ctx);
171
172 DES_key_schedule des1, des2, des3;
173 DES_cblock des_iv;
174 DES_set_key(&kDESKey1, &des1);
175 DES_set_key(&kDESKey2, &des2);
176 DES_set_key(&kDESKey3, &des3);
177
178 /* 3DES Encryption */
179 memcpy(&des_iv, &kDESIV, sizeof(des_iv));
180 printf("About to 3DES-CBC encrypt ");
181 hexdump(kPlaintext, sizeof(kPlaintext));
182 DES_ede3_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &des1, &des2,
183 &des3, &des_iv, DES_ENCRYPT);
184 printf(" got ");
185 hexdump(output, sizeof(kPlaintext));
186
187 /* 3DES Decryption */
188 memcpy(&des_iv, &kDESIV, sizeof(des_iv));
189 printf("About to 3DES-CBC decrypt ");
190 hexdump(kPlaintext, sizeof(kPlaintext));
191 DES_ede3_cbc_encrypt(output, output, sizeof(kPlaintext), &des1, &des2, &des3,
192 &des_iv, DES_DECRYPT);
193 printf(" got ");
194 hexdump(output, sizeof(kPlaintext));
195
196 /* SHA-1 */
197 printf("About to SHA-1 hash ");
198 hexdump(kPlaintext, sizeof(kPlaintext));
199 SHA1(kPlaintext, sizeof(kPlaintext), output);
200 printf(" got ");
201 hexdump(output, SHA_DIGEST_LENGTH);
202
203 /* SHA-256 */
204 printf("About to SHA-256 hash ");
205 hexdump(kPlaintext, sizeof(kPlaintext));
206 SHA256(kPlaintext, sizeof(kPlaintext), output);
207 printf(" got ");
208 hexdump(output, SHA256_DIGEST_LENGTH);
209
210 /* SHA-512 */
211 printf("About to SHA-512 hash ");
212 hexdump(kPlaintext, sizeof(kPlaintext));
213 SHA512(kPlaintext, sizeof(kPlaintext), output);
214 printf(" got ");
215 hexdump(output, SHA512_DIGEST_LENGTH);
216
217 RSA *rsa_key = RSA_new();
218 printf("About to generate RSA key\n");
219 if (!RSA_generate_key_fips(rsa_key, 2048, NULL)) {
220 printf("RSA_generate_key_fips failed\n");
221 return 0;
222 }
223
224 /* RSA Sign */
225 unsigned sig_len;
226 printf("About to RSA sign ");
227 hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256));
228 if (!RSA_sign(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), output,
229 &sig_len, rsa_key)) {
230 printf("RSA Sign failed\n");
231 return 0;
232 }
233 printf(" got ");
234 hexdump(output, sig_len);
235
236 /* RSA Verify */
237 printf("About to RSA verify ");
238 hexdump(output, sig_len);
239 if (!RSA_verify(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256),
240 output, sig_len, rsa_key)) {
241 printf("RSA Verify failed.\n");
242 return 0;
243 }
244
245 RSA_free(rsa_key);
246
247 /* Generating a key with a null output parameter. */
248 printf("About to generate RSA key with null output\n");
249 if (!RSA_generate_key_fips(NULL, 2048, NULL)) {
250 printf("RSA_generate_key_fips failed with null output parameter\n");
251 ERR_clear_error();
252 } else {
253 printf(
254 "RSA_generate_key_fips unexpectedly succeeded with null output "
255 "parameter\n");
256 return 0;
257 }
258
259 EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
260 if (ec_key == NULL) {
261 printf("invalid ECDSA key\n");
262 return 0;
263 }
264
265 printf("About to generate P-256 key\n");
266 if (!EC_KEY_generate_key_fips(ec_key)) {
267 printf("EC_KEY_generate_key_fips failed\n");
268 return 0;
269 }
270
271 /* Primitive Z Computation */
272 const EC_GROUP *const ec_group = EC_KEY_get0_group(ec_key);
273 EC_POINT *z_point = EC_POINT_new(ec_group);
274 uint8_t z_result[65];
275 printf("About to compute key-agreement Z with P-256:\n");
276 if (!EC_POINT_mul(ec_group, z_point, NULL, EC_KEY_get0_public_key(ec_key),
277 EC_KEY_get0_private_key(ec_key), NULL) ||
278 EC_POINT_point2oct(ec_group, z_point, POINT_CONVERSION_UNCOMPRESSED,
279 z_result, sizeof(z_result),
280 NULL) != sizeof(z_result)) {
281 fprintf(stderr, "EC_POINT_mul failed.\n");
282 return 0;
283 }
284 EC_POINT_free(z_point);
285
286 printf(" got ");
287 hexdump(z_result, sizeof(z_result));
288
289 /* ECDSA Sign/Verify PWCT */
290 printf("About to ECDSA sign ");
291 hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256));
292 ECDSA_SIG *sig =
293 ECDSA_do_sign(kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key);
294 if (sig == NULL || !ECDSA_do_verify(kPlaintextSHA256,
295 sizeof(kPlaintextSHA256), sig, ec_key)) {
296 printf("ECDSA Sign/Verify PWCT failed.\n");
297 return 0;
298 }
299
300 ECDSA_SIG_free(sig);
301 EC_KEY_free(ec_key);
302
303 /* Generating a key with a null output pointer. */
304 printf("About to generate P-256 key with NULL output\n");
305 if (!EC_KEY_generate_key_fips(NULL)) {
306 printf("EC_KEY_generate_key_fips failed with a NULL output pointer.\n");
307 ERR_clear_error();
308 } else {
309 printf(
310 "EC_KEY_generate_key_fips unexpectedly succeeded with a NULL output "
311 "pointer.\n");
312 return 0;
313 }
314
315 /* ECDSA with an invalid public key. */
316 ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
317 static const uint8_t kNotValidX926[] = {1, 2, 3, 4, 5, 6};
318 if (!EC_KEY_oct2key(ec_key, kNotValidX926, sizeof(kNotValidX926),
319 /*ctx=*/NULL)) {
320 printf("Error while parsing invalid ECDSA public key\n");
321 } else {
322 printf("Unexpected success while parsing invalid ECDSA public key\n");
323 return 0;
324 }
325 EC_KEY_free(ec_key);
326
327 /* DBRG */
328 CTR_DRBG_STATE drbg;
329 printf("About to seed CTR-DRBG with ");
330 hexdump(kDRBGEntropy, sizeof(kDRBGEntropy));
331 if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization,
332 sizeof(kDRBGPersonalization)) ||
333 !CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD,
334 sizeof(kDRBGAD)) ||
335 !CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) ||
336 !CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD,
337 sizeof(kDRBGAD))) {
338 printf("DRBG failed\n");
339 return 0;
340 }
341 printf(" generated ");
342 hexdump(output, sizeof(output));
343 CTR_DRBG_clear(&drbg);
344
345 /* HKDF */
346 printf("About to run HKDF\n");
347 uint8_t hkdf_output[32];
348 if (!HKDF(hkdf_output, sizeof(hkdf_output), EVP_sha256(), kAESKey,
349 sizeof(kAESKey), (const uint8_t *)"salt", 4, kPlaintextSHA256,
350 sizeof(kPlaintextSHA256))) {
351 fprintf(stderr, "HKDF failed.\n");
352 return 0;
353 }
354 printf(" got ");
355 hexdump(hkdf_output, sizeof(hkdf_output));
356
357 /* TLS v1.0 KDF */
358 printf("About to run TLS v1.0 KDF\n");
359 uint8_t tls10_output[32];
360 if (!CRYPTO_tls1_prf(EVP_md5_sha1(), tls10_output, sizeof(tls10_output),
361 kAESKey, sizeof(kAESKey), "foo", 3, kPlaintextSHA256,
362 sizeof(kPlaintextSHA256), kPlaintextSHA256,
363 sizeof(kPlaintextSHA256))) {
364 fprintf(stderr, "TLS v1.0 KDF failed.\n");
365 return 0;
366 }
367 printf(" got ");
368 hexdump(tls10_output, sizeof(tls10_output));
369
370 /* TLS v1.2 KDF */
371 printf("About to run TLS v1.2 KDF\n");
372 uint8_t tls12_output[32];
373 if (!CRYPTO_tls1_prf(EVP_sha256(), tls12_output, sizeof(tls12_output),
374 kAESKey, sizeof(kAESKey), "foo", 3, kPlaintextSHA256,
375 sizeof(kPlaintextSHA256), kPlaintextSHA256,
376 sizeof(kPlaintextSHA256))) {
377 fprintf(stderr, "TLS v1.2 KDF failed.\n");
378 return 0;
379 }
380 printf(" got ");
381 hexdump(tls12_output, sizeof(tls12_output));
382
383 /* TLS v1.3 KDF */
384 printf("About to run TLS v1.3 KDF\n");
385 uint8_t tls13_output[32];
386 if (!CRYPTO_tls13_hkdf_expand_label(
387 tls13_output, sizeof(tls13_output), EVP_sha256(), kAESKey,
388 sizeof(kAESKey), (const uint8_t *)"foo", 3, kPlaintextSHA256,
389 sizeof(kPlaintextSHA256))) {
390 fprintf(stderr, "TLS v1.3 KDF failed.\n");
391 return 0;
392 }
393 printf(" got ");
394 hexdump(tls13_output, sizeof(tls13_output));
395
396 /* FFDH */
397 printf("About to compute FFDH key-agreement:\n");
398 DH *dh = DH_get_rfc7919_2048();
399 uint8_t dh_result[2048 / 8];
400 if (!dh || !DH_generate_key(dh) || sizeof(dh_result) != DH_size(dh) ||
401 DH_compute_key_padded(dh_result, DH_get0_pub_key(dh), dh) !=
402 sizeof(dh_result)) {
403 fprintf(stderr, "FFDH failed.\n");
404 return 0;
405 }
406 DH_free(dh);
407
408 printf(" got ");
409 hexdump(dh_result, sizeof(dh_result));
410
411 /* ML-KEM */
412 printf("About to generate ML-KEM key:\n");
413 auto mlkem_public_key_bytes =
414 std::make_unique<uint8_t[]>(BCM_MLKEM768_PUBLIC_KEY_BYTES);
415 auto mlkem_private_key = std::make_unique<BCM_mlkem768_private_key>();
416 if (BCM_mlkem768_generate_key_fips(mlkem_public_key_bytes.get(), nullptr,
417 mlkem_private_key.get()) !=
418 bcm_status::approved) {
419 fprintf(stderr, "ML-KEM generation failed");
420 return 0;
421 }
422 printf(" got ");
423 hexdump(mlkem_public_key_bytes.get(), BCM_MLKEM768_PUBLIC_KEY_BYTES);
424
425 printf("About to do ML-KEM encap:\n");
426 auto mlkem_ciphertext =
427 std::make_unique<uint8_t[]>(BCM_MLKEM768_CIPHERTEXT_BYTES);
428 uint8_t mlkem_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
429 auto mlkem_public_key = std::make_unique<BCM_mlkem768_public_key>();
430 BCM_mlkem768_public_from_private(mlkem_public_key.get(),
431 mlkem_private_key.get());
432 if (BCM_mlkem768_encap(mlkem_ciphertext.get(), mlkem_shared_secret,
433 mlkem_public_key.get()) != bcm_infallible::approved) {
434 fprintf(stderr, "ML-KEM encap failed");
435 return 0;
436 }
437 printf(" got ");
438 hexdump(mlkem_shared_secret, sizeof(mlkem_shared_secret));
439
440 printf("About to do ML-KEM decap:\n");
441 if (BCM_mlkem768_decap(mlkem_shared_secret, mlkem_ciphertext.get(),
442 BCM_MLKEM768_CIPHERTEXT_BYTES,
443 mlkem_private_key.get()) != bcm_status::approved) {
444 fprintf(stderr, "ML-KEM decap failed");
445 return 0;
446 }
447 printf(" got ");
448 hexdump(mlkem_shared_secret, sizeof(mlkem_shared_secret));
449
450 /* ML-DSA */
451 printf("About to generate ML-DSA key:\n");
452 auto mldsa_public_key_bytes =
453 std::make_unique<uint8_t[]>(BCM_MLDSA65_PUBLIC_KEY_BYTES);
454 uint8_t mldsa_seed[BCM_MLDSA_SEED_BYTES];
455 auto mldsa_priv = std::make_unique<BCM_mldsa65_private_key>();
456 if (BCM_mldsa65_generate_key_fips(mldsa_public_key_bytes.get(), mldsa_seed,
457 mldsa_priv.get()) != bcm_status::approved) {
458 fprintf(stderr, "ML-DSA keygen failed");
459 return 0;
460 }
461 printf(" got ");
462 hexdump(mldsa_public_key_bytes.get(), BCM_MLDSA65_PUBLIC_KEY_BYTES);
463
464 printf("About to ML-DSA sign:\n");
465 auto mldsa_sig = std::make_unique<uint8_t[]>(BCM_MLDSA65_SIGNATURE_BYTES);
466 if (BCM_mldsa65_sign(mldsa_sig.get(), mldsa_priv.get(), nullptr, 0, nullptr,
467 0) != bcm_status::approved) {
468 fprintf(stderr, "ML-DSA sign failed");
469 return 0;
470 }
471 printf(" got ");
472 hexdump(mldsa_sig.get(), BCM_MLDSA65_SIGNATURE_BYTES);
473
474 printf("About to ML-DSA verify:\n");
475 auto mldsa_pub = std::make_unique<BCM_mldsa65_public_key>();
476 if (BCM_mldsa65_public_from_private(mldsa_pub.get(), mldsa_priv.get()) !=
477 bcm_status::approved ||
478 BCM_mldsa65_verify(mldsa_pub.get(), mldsa_sig.get(), nullptr, 0, nullptr,
479 0) != bcm_status::approved) {
480 fprintf(stderr, "ML-DSA verify failed");
481 return 0;
482 }
483
484 /* SLH-DSA */
485 printf("About to generate SLH-DSA key:\n");
486 uint8_t slhdsa_seed[3 * BCM_SLHDSA_SHA2_128S_N] = {0};
487 uint8_t slhdsa_pub[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES];
488 uint8_t slhdsa_priv[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES];
489 BCM_slhdsa_sha2_128s_generate_key_from_seed(slhdsa_pub, slhdsa_priv,
490 slhdsa_seed);
491 printf(" got ");
492 hexdump(slhdsa_pub, sizeof(slhdsa_pub));
493
494 printf("About to SLH-DSA sign:\n");
495 auto slhdsa_sig =
496 std::make_unique<uint8_t[]>(BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES);
497 if (BCM_slhdsa_sha2_128s_sign(slhdsa_sig.get(), slhdsa_priv, nullptr, 0,
498 nullptr, 0) != bcm_status::approved) {
499 fprintf(stderr, "SLH-DSA sign failed");
500 return 0;
501 }
502 printf(" got ");
503 hexdump(slhdsa_sig.get(), 128); // value too long to fully print
504
505 printf("About to SLH-DSA verify:\n");
506 if (BCM_slhdsa_sha2_128s_verify(
507 slhdsa_sig.get(), BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES, slhdsa_pub,
508 nullptr, 0, nullptr, 0) != bcm_status::approved) {
509 fprintf(stderr, "SLH-DSA verify failed");
510 return 0;
511 }
512
513 printf("PASS\n");
514 return 1;
515 #endif // !defined(BORINGSSL_FIPS)
516 }
517
main(int argc,char ** argv)518 int main(int argc, char **argv) {
519 if (!run_test()) {
520 printf("FAIL\n");
521 fflush(stdout);
522 abort();
523 }
524 return 0;
525 }
526