260 lines
8.1 KiB
C
260 lines
8.1 KiB
C
|
/* Copyright (c) 2017, Google Inc.
|
||
|
*
|
||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||
|
* purpose with or without fee is hereby granted, provided that the above
|
||
|
* copyright notice and this permission notice appear in all copies.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||
|
|
||
|
/* test_fips exercises various cryptographic primitives for demonstration
|
||
|
* purposes in the validation process only. */
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <openssl/aead.h>
|
||
|
#include <openssl/aes.h>
|
||
|
#include <openssl/bn.h>
|
||
|
#include <openssl/crypto.h>
|
||
|
#include <openssl/des.h>
|
||
|
#include <openssl/ecdsa.h>
|
||
|
#include <openssl/ec_key.h>
|
||
|
#include <openssl/hmac.h>
|
||
|
#include <openssl/nid.h>
|
||
|
#include <openssl/rsa.h>
|
||
|
#include <openssl/sha.h>
|
||
|
|
||
|
#include "../crypto/fipsmodule/rand/internal.h"
|
||
|
#include "../crypto/internal.h"
|
||
|
|
||
|
|
||
|
static void hexdump(const void *a, size_t len) {
|
||
|
const unsigned char *in = (const unsigned char *)a;
|
||
|
for (size_t i = 0; i < len; i++) {
|
||
|
printf("%02x", in[i]);
|
||
|
}
|
||
|
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv) {
|
||
|
CRYPTO_library_init();
|
||
|
|
||
|
static const uint8_t kAESKey[16] = "BoringCrypto Key";
|
||
|
static const uint8_t kPlaintext[64] =
|
||
|
"BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!";
|
||
|
static const DES_cblock kDESKey1 = {"BCMDESK1"};
|
||
|
static const DES_cblock kDESKey2 = {"BCMDESK2"};
|
||
|
static const DES_cblock kDESKey3 = {"BCMDESK3"};
|
||
|
static const DES_cblock kDESIV = {"BCMDESIV"};
|
||
|
static const uint8_t kPlaintextSHA256[32] = {
|
||
|
0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb,
|
||
|
0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb,
|
||
|
0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, 0x0f};
|
||
|
const uint8_t kDRBGEntropy[48] =
|
||
|
"DBRG Initial Entropy ";
|
||
|
const uint8_t kDRBGPersonalization[18] = "BCMPersonalization";
|
||
|
const uint8_t kDRBGAD[16] = "BCM DRBG AD ";
|
||
|
const uint8_t kDRBGEntropy2[48] =
|
||
|
"DBRG Reseed Entropy ";
|
||
|
|
||
|
AES_KEY aes_key;
|
||
|
uint8_t aes_iv[16];
|
||
|
uint8_t output[256];
|
||
|
|
||
|
/* AES-CBC Encryption */
|
||
|
memset(aes_iv, 0, sizeof(aes_iv));
|
||
|
if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
|
||
|
printf("AES_set_encrypt_key failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
printf("About to AES-CBC encrypt ");
|
||
|
hexdump(kPlaintext, sizeof(kPlaintext));
|
||
|
AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv,
|
||
|
AES_ENCRYPT);
|
||
|
printf(" got ");
|
||
|
hexdump(output, sizeof(kPlaintext));
|
||
|
|
||
|
/* AES-CBC Decryption */
|
||
|
memset(aes_iv, 0, sizeof(aes_iv));
|
||
|
if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
|
||
|
printf("AES decrypt failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
printf("About to AES-CBC decrypt ");
|
||
|
hexdump(output, sizeof(kPlaintext));
|
||
|
AES_cbc_encrypt(output, output, sizeof(kPlaintext), &aes_key, aes_iv,
|
||
|
AES_DECRYPT);
|
||
|
printf(" got ");
|
||
|
hexdump(output, sizeof(kPlaintext));
|
||
|
|
||
|
size_t out_len;
|
||
|
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
|
||
|
OPENSSL_memset(nonce, 0, sizeof(nonce));
|
||
|
EVP_AEAD_CTX aead_ctx;
|
||
|
if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
|
||
|
sizeof(kAESKey), 0, NULL)) {
|
||
|
printf("EVP_AEAD_CTX_init failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
/* AES-GCM Encryption */
|
||
|
printf("About to AES-GCM seal ");
|
||
|
hexdump(output, sizeof(kPlaintext));
|
||
|
if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
|
||
|
EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
|
||
|
kPlaintext, sizeof(kPlaintext), NULL, 0)) {
|
||
|
printf("AES-GCM encrypt failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
printf(" got ");
|
||
|
hexdump(output, out_len);
|
||
|
|
||
|
/* AES-GCM Decryption */
|
||
|
printf("About to AES-GCM open ");
|
||
|
hexdump(output, out_len);
|
||
|
if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
|
||
|
EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
|
||
|
output, out_len, NULL, 0)) {
|
||
|
printf("AES-GCM decrypt failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
printf(" got ");
|
||
|
hexdump(output, out_len);
|
||
|
|
||
|
EVP_AEAD_CTX_cleanup(&aead_ctx);
|
||
|
|
||
|
DES_key_schedule des1, des2, des3;
|
||
|
DES_cblock des_iv;
|
||
|
DES_set_key(&kDESKey1, &des1);
|
||
|
DES_set_key(&kDESKey2, &des2);
|
||
|
DES_set_key(&kDESKey3, &des3);
|
||
|
|
||
|
/* 3DES Encryption */
|
||
|
memcpy(&des_iv, &kDESIV, sizeof(des_iv));
|
||
|
printf("About to 3DES-CBC encrypt ");
|
||
|
hexdump(kPlaintext, sizeof(kPlaintext));
|
||
|
DES_ede3_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &des1, &des2,
|
||
|
&des3, &des_iv, DES_ENCRYPT);
|
||
|
printf(" got ");
|
||
|
hexdump(output, sizeof(kPlaintext));
|
||
|
|
||
|
/* 3DES Decryption */
|
||
|
memcpy(&des_iv, &kDESIV, sizeof(des_iv));
|
||
|
printf("About to 3DES-CBC decrypt ");
|
||
|
hexdump(kPlaintext, sizeof(kPlaintext));
|
||
|
DES_ede3_cbc_encrypt(output, output, sizeof(kPlaintext), &des1,
|
||
|
&des2, &des3, &des_iv, DES_DECRYPT);
|
||
|
printf(" got ");
|
||
|
hexdump(output, sizeof(kPlaintext));
|
||
|
|
||
|
/* SHA-1 */
|
||
|
printf("About to SHA-1 hash ");
|
||
|
hexdump(kPlaintext, sizeof(kPlaintext));
|
||
|
SHA1(kPlaintext, sizeof(kPlaintext), output);
|
||
|
printf(" got ");
|
||
|
hexdump(output, SHA_DIGEST_LENGTH);
|
||
|
|
||
|
/* SHA-256 */
|
||
|
printf("About to SHA-256 hash ");
|
||
|
hexdump(kPlaintext, sizeof(kPlaintext));
|
||
|
SHA256(kPlaintext, sizeof(kPlaintext), output);
|
||
|
printf(" got ");
|
||
|
hexdump(output, SHA256_DIGEST_LENGTH);
|
||
|
|
||
|
/* SHA-512 */
|
||
|
printf("About to SHA-512 hash ");
|
||
|
hexdump(kPlaintext, sizeof(kPlaintext));
|
||
|
SHA512(kPlaintext, sizeof(kPlaintext), output);
|
||
|
printf(" got ");
|
||
|
hexdump(output, SHA512_DIGEST_LENGTH);
|
||
|
|
||
|
RSA *rsa_key = RSA_new();
|
||
|
printf("About to generate RSA key\n");
|
||
|
if (!RSA_generate_key_fips(rsa_key, 2048, NULL)) {
|
||
|
printf("RSA_generate_key_fips failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
/* RSA Sign */
|
||
|
unsigned sig_len;
|
||
|
printf("About to RSA sign ");
|
||
|
hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256));
|
||
|
if (!RSA_sign(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), output,
|
||
|
&sig_len, rsa_key)) {
|
||
|
printf("RSA Sign failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
printf(" got ");
|
||
|
hexdump(output, sig_len);
|
||
|
|
||
|
/* RSA Verify */
|
||
|
printf("About to RSA verify ");
|
||
|
hexdump(output, sig_len);
|
||
|
if (!RSA_verify(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256),
|
||
|
output, sig_len, rsa_key)) {
|
||
|
printf("RSA Verify failed.\n");
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
RSA_free(rsa_key);
|
||
|
|
||
|
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||
|
if (ec_key == NULL) {
|
||
|
printf("invalid ECDSA key\n");
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
printf("About to generate P-256 key\n");
|
||
|
if (!EC_KEY_generate_key_fips(ec_key)) {
|
||
|
printf("EC_KEY_generate_key_fips failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
/* ECDSA Sign/Verify PWCT */
|
||
|
printf("About to ECDSA sign ");
|
||
|
hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256));
|
||
|
ECDSA_SIG *sig =
|
||
|
ECDSA_do_sign(kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key);
|
||
|
if (sig == NULL ||
|
||
|
!ECDSA_do_verify(kPlaintextSHA256, sizeof(kPlaintextSHA256), sig,
|
||
|
ec_key)) {
|
||
|
printf("ECDSA Sign/Verify PWCT failed.\n");
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
ECDSA_SIG_free(sig);
|
||
|
EC_KEY_free(ec_key);
|
||
|
|
||
|
/* DBRG */
|
||
|
CTR_DRBG_STATE drbg;
|
||
|
printf("About to seed CTR-DRBG with ");
|
||
|
hexdump(kDRBGEntropy, sizeof(kDRBGEntropy));
|
||
|
if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization,
|
||
|
sizeof(kDRBGPersonalization)) ||
|
||
|
!CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD,
|
||
|
sizeof(kDRBGAD)) ||
|
||
|
!CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) ||
|
||
|
!CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD,
|
||
|
sizeof(kDRBGAD))) {
|
||
|
printf("DRBG failed\n");
|
||
|
goto err;
|
||
|
}
|
||
|
printf(" generated ");
|
||
|
hexdump(output, sizeof(output));
|
||
|
CTR_DRBG_clear(&drbg);
|
||
|
|
||
|
printf("PASS\n");
|
||
|
return 0;
|
||
|
|
||
|
err:
|
||
|
printf("FAIL\n");
|
||
|
abort();
|
||
|
}
|