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 51#include <openssl/rand.h> 52#include <openssl/fips_rand.h> 53#include <openssl/err.h> 54#include <openssl/bio.h> 55#include <openssl/hmac.h> 56#include <openssl/rsa.h> 57#include <string.h> 58#include <limits.h> 59#include "fips_locl.h" 60 61#ifdef OPENSSL_FIPS 62 63#include <openssl/fips.h> 64 65#ifndef PATH_MAX 66#define PATH_MAX 1024 67#endif 68 69static int fips_selftest_fail; 70static int fips_mode; 71static const void *fips_rand_check; 72 73static void fips_set_mode(int onoff) 74 { 75 int owning_thread = fips_is_owning_thread(); 76 77 if (fips_is_started()) 78 { 79 if (!owning_thread) fips_w_lock(); 80 fips_mode = onoff; 81 if (!owning_thread) 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 { 91 if (!owning_thread) fips_w_lock(); 92 fips_rand_check = rand_check; 93 if (!owning_thread) fips_w_unlock(); 94 } 95 } 96 97int FIPS_mode(void) 98 { 99 int ret = 0; 100 int owning_thread = fips_is_owning_thread(); 101 102 if (fips_is_started()) 103 { 104 if (!owning_thread) fips_r_lock(); 105 ret = fips_mode; 106 if (!owning_thread) fips_r_unlock(); 107 } 108 return ret; 109 } 110 111const void *FIPS_rand_check(void) 112 { 113 const void *ret = 0; 114 int owning_thread = fips_is_owning_thread(); 115 116 if (fips_is_started()) 117 { 118 if (!owning_thread) fips_r_lock(); 119 ret = fips_rand_check; 120 if (!owning_thread) fips_r_unlock(); 121 } 122 return ret; 123 } 124 125int FIPS_selftest_failed(void) 126 { 127 int ret = 0; 128 if (fips_is_started()) 129 { 130 int owning_thread = fips_is_owning_thread(); 131 132 if (!owning_thread) fips_r_lock(); 133 ret = fips_selftest_fail; 134 if (!owning_thread) fips_r_unlock(); 135 } 136 return ret; 137 } 138 139/* Selftest failure fatal exit routine. This will be called 140 * during *any* cryptographic operation. It has the minimum 141 * overhead possible to avoid too big a performance hit. 142 */ 143 144void FIPS_selftest_check(void) 145 { 146 if (fips_selftest_fail) 147 { 148 OpenSSLDie(__FILE__,__LINE__, "FATAL FIPS SELFTEST FAILURE"); 149 } 150 } 151 152void fips_set_selftest_fail(void) 153 { 154 fips_selftest_fail = 1; 155 } 156 157int FIPS_selftest() 158 { 159 160 return FIPS_selftest_sha1() 161 && FIPS_selftest_hmac() 162 && FIPS_selftest_aes() 163 && FIPS_selftest_des() 164 && FIPS_selftest_rsa() 165 && FIPS_selftest_dsa(); 166 } 167 168extern const void *FIPS_text_start(), *FIPS_text_end(); 169extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; 170unsigned char FIPS_signature [20] = { 0 }; 171static const char FIPS_hmac_key[]="etaonrishdlcupfm"; 172 173unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len) 174 { 175 const unsigned char *p1 = FIPS_text_start(); 176 const unsigned char *p2 = FIPS_text_end(); 177 const unsigned char *p3 = FIPS_rodata_start; 178 const unsigned char *p4 = FIPS_rodata_end; 179 HMAC_CTX c; 180 181 HMAC_CTX_init(&c); 182 HMAC_Init(&c,FIPS_hmac_key,strlen(FIPS_hmac_key),EVP_sha1()); 183 184 /* detect overlapping regions */ 185 if (p1<=p3 && p2>=p3) 186 p3=p1, p4=p2>p4?p2:p4, p1=NULL, p2=NULL; 187 else if (p3<=p1 && p4>=p1) 188 p3=p3, p4=p2>p4?p2:p4, p1=NULL, p2=NULL; 189 190 if (p1) 191 HMAC_Update(&c,p1,(size_t)p2-(size_t)p1); 192 193 if (FIPS_signature>=p3 && FIPS_signature<p4) 194 { 195 /* "punch" hole */ 196 HMAC_Update(&c,p3,(size_t)FIPS_signature-(size_t)p3); 197 p3 = FIPS_signature+sizeof(FIPS_signature); 198 if (p3<p4) 199 HMAC_Update(&c,p3,(size_t)p4-(size_t)p3); 200 } 201 else 202 HMAC_Update(&c,p3,(size_t)p4-(size_t)p3); 203 204 HMAC_Final(&c,sig,&len); 205 HMAC_CTX_cleanup(&c); 206 207 return len; 208 } 209 210int FIPS_check_incore_fingerprint(void) 211 { 212 unsigned char sig[EVP_MAX_MD_SIZE]; 213 unsigned int len; 214#if defined(__sgi) && (defined(__mips) || defined(mips)) 215 extern int __dso_displacement[]; 216#else 217 extern int OPENSSL_NONPIC_relocated; 218#endif 219 220 if (FIPS_text_start()==NULL) 221 { 222 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_UNSUPPORTED_PLATFORM); 223 return 0; 224 } 225 226 len=FIPS_incore_fingerprint (sig,sizeof(sig)); 227 228 if (len!=sizeof(FIPS_signature) || 229 memcmp(FIPS_signature,sig,sizeof(FIPS_signature))) 230 { 231 if (FIPS_signature>=FIPS_rodata_start && FIPS_signature<FIPS_rodata_end) 232 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING); 233#if defined(__sgi) && (defined(__mips) || defined(mips)) 234 else if (__dso_displacement!=NULL) 235#else 236 else if (OPENSSL_NONPIC_relocated) 237#endif 238 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED); 239 else 240 FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH); 241 return 0; 242 } 243 244 return 1; 245 } 246 247int FIPS_mode_set(int onoff) 248 { 249 int fips_set_owning_thread(); 250 int fips_clear_owning_thread(); 251 int ret = 0; 252 253 fips_w_lock(); 254 fips_set_started(); 255 fips_set_owning_thread(); 256 257 if(onoff) 258 { 259 unsigned char buf[48]; 260 261 fips_selftest_fail = 0; 262 263 /* Don't go into FIPS mode twice, just so we can do automagic 264 seeding */ 265 if(FIPS_mode()) 266 { 267 FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET); 268 fips_selftest_fail = 1; 269 ret = 0; 270 goto end; 271 } 272 273#ifdef OPENSSL_IA32_SSE2 274 if ((OPENSSL_ia32cap & (1<<25|1<<26)) != (1<<25|1<<26)) 275 { 276 FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM); 277 fips_selftest_fail = 1; 278 ret = 0; 279 goto end; 280 } 281#endif 282 283 if(fips_signature_witness() != FIPS_signature) 284 { 285 FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE); 286 fips_selftest_fail = 1; 287 ret = 0; 288 goto end; 289 } 290 291 if(!FIPS_check_incore_fingerprint()) 292 { 293 fips_selftest_fail = 1; 294 ret = 0; 295 goto end; 296 } 297 298 /* Perform RNG KAT before seeding */ 299 if (!FIPS_selftest_rng()) 300 { 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 { 309 if(RAND_bytes(buf,sizeof buf) <= 0) 310 { 311 fips_selftest_fail = 1; 312 ret = 0; 313 goto end; 314 } 315 FIPS_rand_set_key(buf,32); 316 FIPS_rand_seed(buf+32,16); 317 } 318 319 /* now switch into FIPS mode */ 320 fips_set_rand_check(FIPS_rand_method()); 321 RAND_set_rand_method(FIPS_rand_method()); 322 if(FIPS_selftest()) 323 fips_set_mode(1); 324 else 325 { 326 fips_selftest_fail = 1; 327 ret = 0; 328 goto end; 329 } 330 ret = 1; 331 goto end; 332 } 333 fips_set_mode(0); 334 fips_selftest_fail = 0; 335 ret = 1; 336end: 337 fips_clear_owning_thread(); 338 fips_w_unlock(); 339 return ret; 340 } 341 342void fips_w_lock(void) { CRYPTO_w_lock(CRYPTO_LOCK_FIPS); } 343void fips_w_unlock(void) { CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); } 344void fips_r_lock(void) { CRYPTO_r_lock(CRYPTO_LOCK_FIPS); } 345void fips_r_unlock(void) { CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); } 346 347static int fips_started = 0; 348static unsigned long fips_thread = 0; 349 350void fips_set_started(void) 351 { 352 fips_started = 1; 353 } 354 355int fips_is_started(void) 356 { 357 return fips_started; 358 } 359 360int fips_is_owning_thread(void) 361 { 362 int ret = 0; 363 364 if (fips_is_started()) 365 { 366 CRYPTO_r_lock(CRYPTO_LOCK_FIPS2); 367 if (fips_thread != 0 && fips_thread == CRYPTO_thread_id()) 368 ret = 1; 369 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2); 370 } 371 return ret; 372 } 373 374int fips_set_owning_thread(void) 375 { 376 int ret = 0; 377 378 if (fips_is_started()) 379 { 380 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2); 381 if (fips_thread == 0) 382 { 383 fips_thread = CRYPTO_thread_id(); 384 ret = 1; 385 } 386 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2); 387 } 388 return ret; 389 } 390 391int fips_clear_owning_thread(void) 392 { 393 int ret = 0; 394 395 if (fips_is_started()) 396 { 397 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2); 398 if (fips_thread == CRYPTO_thread_id()) 399 { 400 fips_thread = 0; 401 ret = 1; 402 } 403 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2); 404 } 405 return ret; 406 } 407 408unsigned char *fips_signature_witness(void) 409 { 410 extern unsigned char FIPS_signature[]; 411 return FIPS_signature; 412 } 413 414/* Generalized public key test routine. Signs and verifies the data 415 * supplied in tbs using mesage digest md and setting option digest 416 * flags md_flags. If the 'kat' parameter is not NULL it will 417 * additionally check the signature matches it: a known answer test 418 * The string "fail_str" is used for identification purposes in case 419 * of failure. 420 */ 421 422int fips_pkey_signature_test(EVP_PKEY *pkey, 423 const unsigned char *tbs, int tbslen, 424 const unsigned char *kat, unsigned int katlen, 425 const EVP_MD *digest, unsigned int md_flags, 426 const char *fail_str) 427 { 428 int ret = 0; 429 unsigned char sigtmp[256], *sig = sigtmp; 430 unsigned int siglen; 431 EVP_MD_CTX mctx; 432 EVP_MD_CTX_init(&mctx); 433 434 if ((pkey->type == EVP_PKEY_RSA) 435 && (RSA_size(pkey->pkey.rsa) > sizeof(sigtmp))) 436 { 437 sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa)); 438 if (!sig) 439 { 440 FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE); 441 return 0; 442 } 443 } 444 445 if (tbslen == -1) 446 tbslen = strlen((char *)tbs); 447 448 if (md_flags) 449 M_EVP_MD_CTX_set_flags(&mctx, md_flags); 450 451 if (!EVP_SignInit_ex(&mctx, digest, NULL)) 452 goto error; 453 if (!EVP_SignUpdate(&mctx, tbs, tbslen)) 454 goto error; 455 if (!EVP_SignFinal(&mctx, sig, &siglen, pkey)) 456 goto error; 457 458 if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen))) 459 goto error; 460 461 if (!EVP_VerifyInit_ex(&mctx, digest, NULL)) 462 goto error; 463 if (!EVP_VerifyUpdate(&mctx, tbs, tbslen)) 464 goto error; 465 ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey); 466 467 error: 468 if (sig != sigtmp) 469 OPENSSL_free(sig); 470 EVP_MD_CTX_cleanup(&mctx); 471 if (ret != 1) 472 { 473 FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE); 474 if (fail_str) 475 ERR_add_error_data(2, "Type=", fail_str); 476 return 0; 477 } 478 return 1; 479 } 480 481/* Generalized symmetric cipher test routine. Encrypt data, verify result 482 * against known answer, decrypt and compare with original plaintext. 483 */ 484 485int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, 486 const unsigned char *key, 487 const unsigned char *iv, 488 const unsigned char *plaintext, 489 const unsigned char *ciphertext, 490 int len) 491 { 492 unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE]; 493 unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE]; 494 OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE); 495 if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1) <= 0) 496 return 0; 497 EVP_Cipher(ctx, citmp, plaintext, len); 498 if (memcmp(citmp, ciphertext, len)) 499 return 0; 500 if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0) <= 0) 501 return 0; 502 EVP_Cipher(ctx, pltmp, citmp, len); 503 if (memcmp(pltmp, plaintext, len)) 504 return 0; 505 return 1; 506 } 507 508#if 0 509/* The purpose of this is to ensure the error code exists and the function 510 * name is to keep the error checking script quiet 511 */ 512void hash_final(void) 513 { 514 FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD); 515 } 516#endif 517 518 519#endif 520