Robert Sloan | 8ff0355 | 2017-06-14 12:40:58 -0700 | [diff] [blame^] | 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/des.h> |
| 25 | #include <openssl/ecdsa.h> |
| 26 | #include <openssl/ec_key.h> |
| 27 | #include <openssl/hmac.h> |
| 28 | #include <openssl/nid.h> |
| 29 | #include <openssl/rsa.h> |
| 30 | #include <openssl/sha.h> |
| 31 | |
| 32 | #include "../crypto/fipsmodule/rand/internal.h" |
| 33 | #include "../crypto/internal.h" |
| 34 | |
| 35 | |
| 36 | static void hexdump(const void *a, size_t len) { |
| 37 | const unsigned char *in = (const unsigned char *)a; |
| 38 | for (size_t i = 0; i < len; i++) { |
| 39 | printf("%02x", in[i]); |
| 40 | } |
| 41 | |
| 42 | printf("\n"); |
| 43 | } |
| 44 | |
| 45 | int main(int argc, char **argv) { |
| 46 | CRYPTO_library_init(); |
| 47 | |
| 48 | static const uint8_t kAESKey[16] = "BoringCrypto Key"; |
| 49 | static const uint8_t kPlaintext[64] = |
| 50 | "BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!"; |
| 51 | static const DES_cblock kDESKey1 = {"BCMDESK1"}; |
| 52 | static const DES_cblock kDESKey2 = {"BCMDESK2"}; |
| 53 | static const DES_cblock kDESKey3 = {"BCMDESK3"}; |
| 54 | static const DES_cblock kDESIV = {"BCMDESIV"}; |
| 55 | static const uint8_t kPlaintextSHA256[32] = { |
| 56 | 0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb, |
| 57 | 0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb, |
| 58 | 0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, 0x0f}; |
| 59 | const uint8_t kDRBGEntropy[48] = |
| 60 | "DBRG Initial Entropy "; |
| 61 | const uint8_t kDRBGPersonalization[18] = "BCMPersonalization"; |
| 62 | const uint8_t kDRBGAD[16] = "BCM DRBG AD "; |
| 63 | const uint8_t kDRBGEntropy2[48] = |
| 64 | "DBRG Reseed Entropy "; |
| 65 | |
| 66 | AES_KEY aes_key; |
| 67 | uint8_t aes_iv[16]; |
| 68 | uint8_t output[256]; |
| 69 | |
| 70 | /* AES-CBC Encryption */ |
| 71 | memset(aes_iv, 0, sizeof(aes_iv)); |
| 72 | if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { |
| 73 | printf("AES_set_encrypt_key failed\n"); |
| 74 | goto err; |
| 75 | } |
| 76 | |
| 77 | printf("About to AES-CBC encrypt "); |
| 78 | hexdump(kPlaintext, sizeof(kPlaintext)); |
| 79 | AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv, |
| 80 | AES_ENCRYPT); |
| 81 | printf(" got "); |
| 82 | hexdump(output, sizeof(kPlaintext)); |
| 83 | |
| 84 | /* AES-CBC Decryption */ |
| 85 | memset(aes_iv, 0, sizeof(aes_iv)); |
| 86 | if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { |
| 87 | printf("AES decrypt failed\n"); |
| 88 | goto err; |
| 89 | } |
| 90 | printf("About to AES-CBC decrypt "); |
| 91 | hexdump(output, sizeof(kPlaintext)); |
| 92 | AES_cbc_encrypt(output, output, sizeof(kPlaintext), &aes_key, aes_iv, |
| 93 | AES_DECRYPT); |
| 94 | printf(" got "); |
| 95 | hexdump(output, sizeof(kPlaintext)); |
| 96 | |
| 97 | size_t out_len; |
| 98 | uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; |
| 99 | OPENSSL_memset(nonce, 0, sizeof(nonce)); |
| 100 | EVP_AEAD_CTX aead_ctx; |
| 101 | if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey, |
| 102 | sizeof(kAESKey), 0, NULL)) { |
| 103 | printf("EVP_AEAD_CTX_init failed\n"); |
| 104 | goto err; |
| 105 | } |
| 106 | |
| 107 | /* AES-GCM Encryption */ |
| 108 | printf("About to AES-GCM seal "); |
| 109 | hexdump(output, sizeof(kPlaintext)); |
| 110 | if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce, |
| 111 | EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), |
| 112 | kPlaintext, sizeof(kPlaintext), NULL, 0)) { |
| 113 | printf("AES-GCM encrypt failed\n"); |
| 114 | goto err; |
| 115 | } |
| 116 | printf(" got "); |
| 117 | hexdump(output, out_len); |
| 118 | |
| 119 | /* AES-GCM Decryption */ |
| 120 | printf("About to AES-GCM open "); |
| 121 | hexdump(output, out_len); |
| 122 | if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce, |
| 123 | EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), |
| 124 | output, out_len, NULL, 0)) { |
| 125 | printf("AES-GCM decrypt failed\n"); |
| 126 | goto err; |
| 127 | } |
| 128 | printf(" got "); |
| 129 | hexdump(output, out_len); |
| 130 | |
| 131 | EVP_AEAD_CTX_cleanup(&aead_ctx); |
| 132 | |
| 133 | DES_key_schedule des1, des2, des3; |
| 134 | DES_cblock des_iv; |
| 135 | DES_set_key(&kDESKey1, &des1); |
| 136 | DES_set_key(&kDESKey2, &des2); |
| 137 | DES_set_key(&kDESKey3, &des3); |
| 138 | |
| 139 | /* 3DES Encryption */ |
| 140 | memcpy(&des_iv, &kDESIV, sizeof(des_iv)); |
| 141 | printf("About to 3DES-CBC encrypt "); |
| 142 | hexdump(kPlaintext, sizeof(kPlaintext)); |
| 143 | DES_ede3_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &des1, &des2, |
| 144 | &des3, &des_iv, DES_ENCRYPT); |
| 145 | printf(" got "); |
| 146 | hexdump(output, sizeof(kPlaintext)); |
| 147 | |
| 148 | /* 3DES Decryption */ |
| 149 | memcpy(&des_iv, &kDESIV, sizeof(des_iv)); |
| 150 | printf("About to 3DES-CBC decrypt "); |
| 151 | hexdump(kPlaintext, sizeof(kPlaintext)); |
| 152 | DES_ede3_cbc_encrypt(output, output, sizeof(kPlaintext), &des1, |
| 153 | &des2, &des3, &des_iv, DES_DECRYPT); |
| 154 | printf(" got "); |
| 155 | hexdump(output, sizeof(kPlaintext)); |
| 156 | |
| 157 | /* SHA-1 */ |
| 158 | printf("About to SHA-1 hash "); |
| 159 | hexdump(kPlaintext, sizeof(kPlaintext)); |
| 160 | SHA1(kPlaintext, sizeof(kPlaintext), output); |
| 161 | printf(" got "); |
| 162 | hexdump(output, SHA_DIGEST_LENGTH); |
| 163 | |
| 164 | /* SHA-256 */ |
| 165 | printf("About to SHA-256 hash "); |
| 166 | hexdump(kPlaintext, sizeof(kPlaintext)); |
| 167 | SHA256(kPlaintext, sizeof(kPlaintext), output); |
| 168 | printf(" got "); |
| 169 | hexdump(output, SHA256_DIGEST_LENGTH); |
| 170 | |
| 171 | /* SHA-512 */ |
| 172 | printf("About to SHA-512 hash "); |
| 173 | hexdump(kPlaintext, sizeof(kPlaintext)); |
| 174 | SHA512(kPlaintext, sizeof(kPlaintext), output); |
| 175 | printf(" got "); |
| 176 | hexdump(output, SHA512_DIGEST_LENGTH); |
| 177 | |
| 178 | RSA *rsa_key = RSA_new(); |
| 179 | printf("About to generate RSA key\n"); |
| 180 | if (!RSA_generate_key_fips(rsa_key, 2048, NULL)) { |
| 181 | printf("RSA_generate_key_fips failed\n"); |
| 182 | goto err; |
| 183 | } |
| 184 | |
| 185 | /* RSA Sign */ |
| 186 | unsigned sig_len; |
| 187 | printf("About to RSA sign "); |
| 188 | hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256)); |
| 189 | if (!RSA_sign(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), output, |
| 190 | &sig_len, rsa_key)) { |
| 191 | printf("RSA Sign failed\n"); |
| 192 | goto err; |
| 193 | } |
| 194 | printf(" got "); |
| 195 | hexdump(output, sig_len); |
| 196 | |
| 197 | /* RSA Verify */ |
| 198 | printf("About to RSA verify "); |
| 199 | hexdump(output, sig_len); |
| 200 | if (!RSA_verify(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), |
| 201 | output, sig_len, rsa_key)) { |
| 202 | printf("RSA Verify failed.\n"); |
| 203 | goto err; |
| 204 | } |
| 205 | |
| 206 | RSA_free(rsa_key); |
| 207 | |
| 208 | EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); |
| 209 | if (ec_key == NULL) { |
| 210 | printf("invalid ECDSA key\n"); |
| 211 | goto err; |
| 212 | } |
| 213 | |
| 214 | printf("About to generate P-256 key\n"); |
| 215 | if (!EC_KEY_generate_key_fips(ec_key)) { |
| 216 | printf("EC_KEY_generate_key_fips failed\n"); |
| 217 | goto err; |
| 218 | } |
| 219 | |
| 220 | /* ECDSA Sign/Verify PWCT */ |
| 221 | printf("About to ECDSA sign "); |
| 222 | hexdump(kPlaintextSHA256, sizeof(kPlaintextSHA256)); |
| 223 | ECDSA_SIG *sig = |
| 224 | ECDSA_do_sign(kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key); |
| 225 | if (sig == NULL || |
| 226 | !ECDSA_do_verify(kPlaintextSHA256, sizeof(kPlaintextSHA256), sig, |
| 227 | ec_key)) { |
| 228 | printf("ECDSA Sign/Verify PWCT failed.\n"); |
| 229 | goto err; |
| 230 | } |
| 231 | |
| 232 | ECDSA_SIG_free(sig); |
| 233 | EC_KEY_free(ec_key); |
| 234 | |
| 235 | /* DBRG */ |
| 236 | CTR_DRBG_STATE drbg; |
| 237 | printf("About to seed CTR-DRBG with "); |
| 238 | hexdump(kDRBGEntropy, sizeof(kDRBGEntropy)); |
| 239 | if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization, |
| 240 | sizeof(kDRBGPersonalization)) || |
| 241 | !CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD, |
| 242 | sizeof(kDRBGAD)) || |
| 243 | !CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) || |
| 244 | !CTR_DRBG_generate(&drbg, output, sizeof(output), kDRBGAD, |
| 245 | sizeof(kDRBGAD))) { |
| 246 | printf("DRBG failed\n"); |
| 247 | goto err; |
| 248 | } |
| 249 | printf(" generated "); |
| 250 | hexdump(output, sizeof(output)); |
| 251 | CTR_DRBG_clear(&drbg); |
| 252 | |
| 253 | printf("PASS\n"); |
| 254 | return 0; |
| 255 | |
| 256 | err: |
| 257 | printf("FAIL\n"); |
| 258 | abort(); |
| 259 | } |