| OLD | NEW |
| (Empty) |
| 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 | |
| 69 static int fips_selftest_fail; | |
| 70 static int fips_mode; | |
| 71 static const void *fips_rand_check; | |
| 72 | |
| 73 static 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 | |
| 85 static 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 | |
| 97 int 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 | |
| 111 const 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 | |
| 125 int 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 | |
| 144 void FIPS_selftest_check(void) | |
| 145 { | |
| 146 if (fips_selftest_fail) | |
| 147 { | |
| 148 OpenSSLDie(__FILE__,__LINE__, "FATAL FIPS SELFTEST FAILURE"); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 void fips_set_selftest_fail(void) | |
| 153 { | |
| 154 fips_selftest_fail = 1; | |
| 155 } | |
| 156 | |
| 157 int 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 | |
| 168 extern const void *FIPS_text_start(), *FIPS_text_end(); | |
| 169 extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; | |
| 170 unsigned char FIPS_signature [20] = { 0 }; | |
| 171 static const char FIPS_hmac_key[]="etaonrishdlcupfm"; | |
| 172 | |
| 173 unsigned 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 | |
| 210 int 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 | |
| 247 int 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; | |
| 336 end: | |
| 337 fips_clear_owning_thread(); | |
| 338 fips_w_unlock(); | |
| 339 return ret; | |
| 340 } | |
| 341 | |
| 342 void fips_w_lock(void) { CRYPTO_w_lock(CRYPTO_LOCK_FIPS); } | |
| 343 void fips_w_unlock(void) { CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); } | |
| 344 void fips_r_lock(void) { CRYPTO_r_lock(CRYPTO_LOCK_FIPS); } | |
| 345 void fips_r_unlock(void) { CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); } | |
| 346 | |
| 347 static int fips_started = 0; | |
| 348 static unsigned long fips_thread = 0; | |
| 349 | |
| 350 void fips_set_started(void) | |
| 351 { | |
| 352 fips_started = 1; | |
| 353 } | |
| 354 | |
| 355 int fips_is_started(void) | |
| 356 { | |
| 357 return fips_started; | |
| 358 } | |
| 359 | |
| 360 int 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 | |
| 374 int 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 | |
| 391 int 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 | |
| 408 unsigned 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 | |
| 422 int 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_FAI
LURE); | |
| 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 | |
| 485 int 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 */ | |
| 512 void hash_final(void) | |
| 513 { | |
| 514 FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD); | |
| 515 } | |
| 516 #endif | |
| 517 | |
| 518 | |
| 519 #endif | |
| OLD | NEW |