fips.c revision 296465
1/* ==================================================================== 2 * Copyright (c) 2003 The OpenSSL Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. All advertising materials mentioning features or use of this 17 * software must display the following acknowledgment: 18 * "This product includes software developed by the OpenSSL Project 19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20 * 21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For written permission, please contact 24 * openssl-core@openssl.org. 25 * 26 * 5. Products derived from this software may not be called "OpenSSL" 27 * nor may "OpenSSL" appear in their names without prior written 28 * permission of the OpenSSL Project. 29 * 30 * 6. Redistributions of any form whatsoever must retain the following 31 * acknowledgment: 32 * "This product includes software developed by the OpenSSL Project 33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46 * OF THE POSSIBILITY OF SUCH DAMAGE. 47 * 48 */ 49 50#include <openssl/rand.h> 51#include <openssl/fips_rand.h> 52#include <openssl/err.h> 53#include <openssl/bio.h> 54#include <openssl/hmac.h> 55#include <openssl/rsa.h> 56#include <string.h> 57#include <limits.h> 58#include "fips_locl.h" 59 60#ifdef OPENSSL_FIPS 61 62# include <openssl/fips.h> 63 64# ifndef PATH_MAX 65# define PATH_MAX 1024 66# endif 67 68static int fips_selftest_fail; 69static int fips_mode; 70static const void *fips_rand_check; 71 72static void fips_set_mode(int onoff) 73{ 74 int owning_thread = fips_is_owning_thread(); 75 76 if (fips_is_started()) { 77 if (!owning_thread) 78 fips_w_lock(); 79 fips_mode = onoff; 80 if (!owning_thread) 81 fips_w_unlock(); 82 } 83} 84 85static void fips_set_rand_check(const void *rand_check) 86{ 87 int owning_thread = fips_is_owning_thread(); 88 89 if (fips_is_started()) { 90 if (!owning_thread) 91 fips_w_lock(); 92 fips_rand_check = rand_check; 93 if (!owning_thread) 94 fips_w_unlock(); 95 } 96} 97 98int FIPS_mode(void) 99{ 100 int ret = 0; 101 int owning_thread = fips_is_owning_thread(); 102 103 if (fips_is_started()) { 104 if (!owning_thread) 105 fips_r_lock(); 106 ret = fips_mode; 107 if (!owning_thread) 108 fips_r_unlock(); 109 } 110 return ret; 111} 112 113const void *FIPS_rand_check(void) 114{ 115 const void *ret = 0; 116 int owning_thread = fips_is_owning_thread(); 117 118 if (fips_is_started()) { 119 if (!owning_thread) 120 fips_r_lock(); 121 ret = fips_rand_check; 122 if (!owning_thread) 123 fips_r_unlock(); 124 } 125 return ret; 126} 127 128int FIPS_selftest_failed(void) 129{ 130 int ret = 0; 131 if (fips_is_started()) { 132 int owning_thread = fips_is_owning_thread(); 133 134 if (!owning_thread) 135 fips_r_lock(); 136 ret = fips_selftest_fail; 137 if (!owning_thread) 138 fips_r_unlock(); 139 } 140 return ret; 141} 142 143/* 144 * Selftest failure fatal exit routine. This will be called during *any* 145 * cryptographic operation. It has the minimum overhead possible to avoid too 146 * big a performance hit. 147 */ 148 149void FIPS_selftest_check(void) 150{ 151 if (fips_selftest_fail) { 152 OpenSSLDie(__FILE__, __LINE__, "FATAL FIPS SELFTEST FAILURE"); 153 } 154} 155 156void fips_set_selftest_fail(void) 157{ 158 fips_selftest_fail = 1; 159} 160 161int FIPS_selftest() 162{ 163 164 return FIPS_selftest_sha1() 165 && FIPS_selftest_hmac() 166 && FIPS_selftest_aes() 167 && FIPS_selftest_des() 168 && FIPS_selftest_rsa() 169 && FIPS_selftest_dsa(); 170} 171 172extern const void *FIPS_text_start(), *FIPS_text_end(); 173extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; 174unsigned char FIPS_signature[20] = { 0 }; 175 176static const char FIPS_hmac_key[] = "etaonrishdlcupfm"; 177 178unsigned int FIPS_incore_fingerprint(unsigned char *sig, unsigned int len) 179{ 180 const unsigned char *p1 = FIPS_text_start(); 181 const unsigned char *p2 = FIPS_text_end(); 182 const unsigned char *p3 = FIPS_rodata_start; 183 const unsigned char *p4 = FIPS_rodata_end; 184 HMAC_CTX c; 185 186 HMAC_CTX_init(&c); 187 HMAC_Init(&c, FIPS_hmac_key, strlen(FIPS_hmac_key), EVP_sha1()); 188 189 /* detect overlapping regions */ 190 if (p1 <= p3 && p2 >= p3) 191 p3 = p1, p4 = p2 > p4 ? p2 : p4, p1 = NULL, p2 = NULL; 192 else if (p3 <= p1 && p4 >= p1) 193 p3 = p3, p4 = p2 > p4 ? p2 : p4, p1 = NULL, p2 = NULL; 194 195 if (p1) 196 HMAC_Update(&c, p1, (size_t)p2 - (size_t)p1); 197 198 if (FIPS_signature >= p3 && FIPS_signature < p4) { 199 /* "punch" hole */ 200 HMAC_Update(&c, p3, (size_t)FIPS_signature - (size_t)p3); 201 p3 = FIPS_signature + sizeof(FIPS_signature); 202 if (p3 < p4) 203 HMAC_Update(&c, p3, (size_t)p4 - (size_t)p3); 204 } else 205 HMAC_Update(&c, p3, (size_t)p4 - (size_t)p3); 206 207 HMAC_Final(&c, sig, &len); 208 HMAC_CTX_cleanup(&c); 209 210 return len; 211} 212 213int FIPS_check_incore_fingerprint(void) 214{ 215 unsigned char sig[EVP_MAX_MD_SIZE]; 216 unsigned int len; 217# if defined(__sgi) && (defined(__mips) || defined(mips)) 218 extern int __dso_displacement[]; 219# else 220 extern int OPENSSL_NONPIC_relocated; 221# endif 222 223 if (FIPS_text_start() == NULL) { 224 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT, 225 FIPS_R_UNSUPPORTED_PLATFORM); 226 return 0; 227 } 228 229 len = FIPS_incore_fingerprint(sig, sizeof(sig)); 230 231 if (len != sizeof(FIPS_signature) || 232 memcmp(FIPS_signature, sig, sizeof(FIPS_signature))) { 233 if (FIPS_signature >= FIPS_rodata_start 234 && FIPS_signature < FIPS_rodata_end) 235 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT, 236 FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING); 237# if defined(__sgi) && (defined(__mips) || defined(mips)) 238 else if (__dso_displacement != NULL) 239# else 240 else if (OPENSSL_NONPIC_relocated) 241# endif 242 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT, 243 FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED); 244 else 245 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT, 246 FIPS_R_FINGERPRINT_DOES_NOT_MATCH); 247 return 0; 248 } 249 250 return 1; 251} 252 253int FIPS_mode_set(int onoff) 254{ 255 int fips_set_owning_thread(); 256 int fips_clear_owning_thread(); 257 int ret = 0; 258 259 fips_w_lock(); 260 fips_set_started(); 261 fips_set_owning_thread(); 262 263 if (onoff) { 264 unsigned char buf[48]; 265 266 fips_selftest_fail = 0; 267 268 /* 269 * Don't go into FIPS mode twice, just so we can do automagic seeding 270 */ 271 if (FIPS_mode()) { 272 FIPSerr(FIPS_F_FIPS_MODE_SET, FIPS_R_FIPS_MODE_ALREADY_SET); 273 fips_selftest_fail = 1; 274 ret = 0; 275 goto end; 276 } 277# ifdef OPENSSL_IA32_SSE2 278 if ((OPENSSL_ia32cap & (1 << 25 | 1 << 26)) != (1 << 25 | 1 << 26)) { 279 FIPSerr(FIPS_F_FIPS_MODE_SET, FIPS_R_UNSUPPORTED_PLATFORM); 280 fips_selftest_fail = 1; 281 ret = 0; 282 goto end; 283 } 284# endif 285 286 if (fips_signature_witness() != FIPS_signature) { 287 FIPSerr(FIPS_F_FIPS_MODE_SET, FIPS_R_CONTRADICTING_EVIDENCE); 288 fips_selftest_fail = 1; 289 ret = 0; 290 goto end; 291 } 292 293 if (!FIPS_check_incore_fingerprint()) { 294 fips_selftest_fail = 1; 295 ret = 0; 296 goto end; 297 } 298 299 /* Perform RNG KAT before seeding */ 300 if (!FIPS_selftest_rng()) { 301 fips_selftest_fail = 1; 302 ret = 0; 303 goto end; 304 } 305 306 /* automagically seed PRNG if not already seeded */ 307 if (!FIPS_rand_status()) { 308 if (RAND_bytes(buf, sizeof buf) <= 0) { 309 fips_selftest_fail = 1; 310 ret = 0; 311 goto end; 312 } 313 FIPS_rand_set_key(buf, 32); 314 FIPS_rand_seed(buf + 32, 16); 315 } 316 317 /* now switch into FIPS mode */ 318 fips_set_rand_check(FIPS_rand_method()); 319 RAND_set_rand_method(FIPS_rand_method()); 320 if (FIPS_selftest()) 321 fips_set_mode(1); 322 else { 323 fips_selftest_fail = 1; 324 ret = 0; 325 goto end; 326 } 327 ret = 1; 328 goto end; 329 } 330 fips_set_mode(0); 331 fips_selftest_fail = 0; 332 ret = 1; 333 end: 334 fips_clear_owning_thread(); 335 fips_w_unlock(); 336 return ret; 337} 338 339void fips_w_lock(void) 340{ 341 CRYPTO_w_lock(CRYPTO_LOCK_FIPS); 342} 343 344void fips_w_unlock(void) 345{ 346 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); 347} 348 349void fips_r_lock(void) 350{ 351 CRYPTO_r_lock(CRYPTO_LOCK_FIPS); 352} 353 354void fips_r_unlock(void) 355{ 356 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); 357} 358 359static int fips_started = 0; 360static unsigned long fips_thread = 0; 361 362void fips_set_started(void) 363{ 364 fips_started = 1; 365} 366 367int fips_is_started(void) 368{ 369 return fips_started; 370} 371 372int fips_is_owning_thread(void) 373{ 374 int ret = 0; 375 376 if (fips_is_started()) { 377 CRYPTO_r_lock(CRYPTO_LOCK_FIPS2); 378 if (fips_thread != 0 && fips_thread == CRYPTO_thread_id()) 379 ret = 1; 380 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2); 381 } 382 return ret; 383} 384 385int fips_set_owning_thread(void) 386{ 387 int ret = 0; 388 389 if (fips_is_started()) { 390 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2); 391 if (fips_thread == 0) { 392 fips_thread = CRYPTO_thread_id(); 393 ret = 1; 394 } 395 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2); 396 } 397 return ret; 398} 399 400int fips_clear_owning_thread(void) 401{ 402 int ret = 0; 403 404 if (fips_is_started()) { 405 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2); 406 if (fips_thread == CRYPTO_thread_id()) { 407 fips_thread = 0; 408 ret = 1; 409 } 410 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2); 411 } 412 return ret; 413} 414 415unsigned char *fips_signature_witness(void) 416{ 417 extern unsigned char FIPS_signature[]; 418 return FIPS_signature; 419} 420 421/* 422 * Generalized public key test routine. Signs and verifies the data supplied 423 * in tbs using mesage digest md and setting option digest flags md_flags. If 424 * the 'kat' parameter is not NULL it will additionally check the signature 425 * matches it: a known answer test The string "fail_str" is used for 426 * identification purposes in case of failure. 427 */ 428 429int fips_pkey_signature_test(EVP_PKEY *pkey, 430 const unsigned char *tbs, int tbslen, 431 const unsigned char *kat, unsigned int katlen, 432 const EVP_MD *digest, unsigned int md_flags, 433 const char *fail_str) 434{ 435 int ret = 0; 436 unsigned char sigtmp[256], *sig = sigtmp; 437 unsigned int siglen; 438 EVP_MD_CTX mctx; 439 EVP_MD_CTX_init(&mctx); 440 441 if ((pkey->type == EVP_PKEY_RSA) 442 && (RSA_size(pkey->pkey.rsa) > sizeof(sigtmp))) { 443 sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa)); 444 if (!sig) { 445 FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST, ERR_R_MALLOC_FAILURE); 446 return 0; 447 } 448 } 449 450 if (tbslen == -1) 451 tbslen = strlen((char *)tbs); 452 453 if (md_flags) 454 M_EVP_MD_CTX_set_flags(&mctx, md_flags); 455 456 if (!EVP_SignInit_ex(&mctx, digest, NULL)) 457 goto error; 458 if (!EVP_SignUpdate(&mctx, tbs, tbslen)) 459 goto error; 460 if (!EVP_SignFinal(&mctx, sig, &siglen, pkey)) 461 goto error; 462 463 if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen))) 464 goto error; 465 466 if (!EVP_VerifyInit_ex(&mctx, digest, NULL)) 467 goto error; 468 if (!EVP_VerifyUpdate(&mctx, tbs, tbslen)) 469 goto error; 470 ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey); 471 472 error: 473 if (sig != sigtmp) 474 OPENSSL_free(sig); 475 EVP_MD_CTX_cleanup(&mctx); 476 if (ret != 1) { 477 FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST, FIPS_R_TEST_FAILURE); 478 if (fail_str) 479 ERR_add_error_data(2, "Type=", fail_str); 480 return 0; 481 } 482 return 1; 483} 484 485/* 486 * Generalized symmetric cipher test routine. Encrypt data, verify result 487 * against known answer, decrypt and compare with original plaintext. 488 */ 489 490int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, 491 const unsigned char *key, 492 const unsigned char *iv, 493 const unsigned char *plaintext, 494 const unsigned char *ciphertext, int len) 495{ 496 unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE]; 497 unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE]; 498 OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE); 499 if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1) <= 0) 500 return 0; 501 EVP_Cipher(ctx, citmp, plaintext, len); 502 if (memcmp(citmp, ciphertext, len)) 503 return 0; 504 if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0) <= 0) 505 return 0; 506 EVP_Cipher(ctx, pltmp, citmp, len); 507 if (memcmp(pltmp, plaintext, len)) 508 return 0; 509 return 1; 510} 511 512# if 0 513/* 514 * The purpose of this is to ensure the error code exists and the function 515 * name is to keep the error checking script quiet 516 */ 517void hash_final(void) 518{ 519 FIPSerr(FIPS_F_HASH_FINAL, FIPS_R_NON_FIPS_METHOD); 520} 521# endif 522 523#endif 524