2323#include <sys/mman.h>
2424#include <unistd.h>
2525#endif
26- #if defined(BORINGSSL_FIPS ) && defined(OPENSSL_WINDOWS )
27- #include <windows.h>
28- #endif
2926
3027// On Windows place the bcm code in a specific section that uses Grouped Sections
3128// to control the order. $b section will place bcm in between the start/end markers
@@ -299,93 +296,6 @@ static void BORINGSSL_bcm_power_on_self_test(void) {
299296}
300297
301298#if !defined(OPENSSL_ASAN )
302-
303- #if defined(OPENSSL_WINDOWS ) && defined(OPENSSL_AARCH64 ) && \
304- defined(BORINGSSL_SHARED_LIBRARY )
305- // On ARM64 Windows, ASLR is mandatory and cannot be disabled. The PE loader
306- // applies base relocations to absolute address references within the .fipstx
307- // and .fipsco sections, making the in-memory content dependent on the DLL's
308- // load address. The FIPS build uses capture_hash.go to compute the integrity
309- // hash from precrypto.dll loaded in one process, then embeds that hash in
310- // crypto.dll which loads in a different process at a different ASLR address.
311- // To make the hash deterministic we copy each FIPS section and reverse the
312- // base relocations before hashing.
313- //
314- // |buf| is a copy of the section content, |buf_size| its length,
315- // |section_rva| the section's RVA in the PE image, |delta| is
316- // actual_base - preferred_base, and |reloc_table|/|reloc_table_size|
317- // describe the PE base relocation directory. |out_count| receives the
318- // number of fixups that were reversed.
319- static void fips_undo_base_relocations (
320- uint8_t * buf , size_t buf_size , uintptr_t section_rva , intptr_t delta ,
321- const uint8_t * reloc_table , size_t reloc_table_size ,
322- size_t * out_count ) {
323- const uint8_t * reloc_ptr = reloc_table ;
324- const uint8_t * reloc_end = reloc_table + reloc_table_size ;
325- size_t count_undone = 0 ;
326-
327- while (reloc_ptr + sizeof (IMAGE_BASE_RELOCATION ) <= reloc_end ) {
328- const IMAGE_BASE_RELOCATION * block = (const IMAGE_BASE_RELOCATION * )reloc_ptr ;
329- if (block -> SizeOfBlock < sizeof (IMAGE_BASE_RELOCATION ) ||
330- reloc_ptr + block -> SizeOfBlock > reloc_end ) {
331- break ;
332- }
333-
334- DWORD page_rva = block -> VirtualAddress ;
335- DWORD count =
336- (block -> SizeOfBlock - sizeof (IMAGE_BASE_RELOCATION )) / sizeof (WORD );
337- const WORD * entries = (const WORD * )(reloc_ptr + sizeof (IMAGE_BASE_RELOCATION ));
338-
339- for (DWORD i = 0 ; i < count ; i ++ ) {
340- int type = entries [i ] >> 12 ;
341- DWORD offset = entries [i ] & 0xFFF ;
342- uintptr_t reloc_rva = (uintptr_t )page_rva + offset ;
343-
344- if (reloc_rva < section_rva ||
345- reloc_rva >= section_rva + buf_size ) {
346- continue ;
347- }
348-
349- size_t buf_offset = (size_t )(reloc_rva - section_rva );
350-
351- switch (type ) {
352- case IMAGE_REL_BASED_ABSOLUTE :
353- break ;
354- case IMAGE_REL_BASED_DIR64 :
355- if (buf_offset + sizeof (uint64_t ) <= buf_size ) {
356- uint64_t val ;
357- memcpy (& val , buf + buf_offset , sizeof (val ));
358- val -= (uint64_t )delta ;
359- memcpy (buf + buf_offset , & val , sizeof (val ));
360- count_undone ++ ;
361- }
362- break ;
363- case IMAGE_REL_BASED_HIGHLOW :
364- if (buf_offset + sizeof (uint32_t ) <= buf_size ) {
365- uint32_t val ;
366- memcpy (& val , buf + buf_offset , sizeof (val ));
367- val -= (uint32_t )delta ;
368- memcpy (buf + buf_offset , & val , sizeof (val ));
369- count_undone ++ ;
370- }
371- break ;
372- default :
373- fprintf (stderr , " RELOC: unhandled type %d at RVA 0x%llx\n" ,
374- type , (unsigned long long )reloc_rva );
375- count_undone ++ ;
376- break ;
377- }
378- }
379-
380- reloc_ptr += block -> SizeOfBlock ;
381- }
382-
383- if (out_count ) {
384- * out_count = count_undone ;
385- }
386- }
387- #endif // OPENSSL_WINDOWS && OPENSSL_AARCH64 && BORINGSSL_SHARED_LIBRARY
388-
389299int BORINGSSL_integrity_test (void ) {
390300 const uint8_t * const start = BORINGSSL_bcm_text_start ;
391301 const uint8_t * const end = BORINGSSL_bcm_text_end ;
@@ -423,42 +333,6 @@ int BORINGSSL_integrity_test(void) {
423333 assert_not_within (rodata_start , & OPENSSL_armcap_P , "OPENSSL_armcap_P" , rodata_end );
424334#endif
425335
426- // Diagnostic output for FIPS integrity test debugging. This helps diagnose
427- // issues where the hash captured from precrypto differs from the hash
428- // computed at runtime from crypto (e.g. Windows ARM64 FIPS shared builds).
429- // capture_hash.go uses pattern-based parsing, so extra output here is safe.
430- #if defined(BORINGSSL_SHARED_LIBRARY )
431- {
432- const uint8_t * const hash_addr = BORINGSSL_bcm_text_hash ;
433- const int hash_in_rodata =
434- (hash_addr >= rodata_start && hash_addr < rodata_end ) ? 1 : 0 ;
435- const int hash_in_text =
436- (hash_addr >= start && hash_addr < end ) ? 1 : 0 ;
437- fprintf (stderr , "FIPS integrity diagnostics:\n" );
438- fprintf (stderr , " text: %p - %p (size: 0x%llx)\n" ,
439- (const void * )start , (const void * )end ,
440- (unsigned long long )(end - start ));
441- fprintf (stderr , " rodata: %p - %p (size: 0x%llx)\n" ,
442- (const void * )rodata_start , (const void * )rodata_end ,
443- (unsigned long long )(rodata_end - rodata_start ));
444- fprintf (stderr , " BORINGSSL_bcm_text_hash @ %p (in_rodata=%d, in_text=%d)\n" ,
445- (const void * )hash_addr , hash_in_rodata , hash_in_text );
446- fprintf (stderr , " text first 8 bytes: %02x%02x%02x%02x%02x%02x%02x%02x\n" ,
447- start [0 ], start [1 ], start [2 ], start [3 ],
448- start [4 ], start [5 ], start [6 ], start [7 ]);
449- fprintf (stderr , " text last 8 bytes: %02x%02x%02x%02x%02x%02x%02x%02x\n" ,
450- end [-8 ], end [-7 ], end [-6 ], end [-5 ],
451- end [-4 ], end [-3 ], end [-2 ], end [-1 ]);
452- fprintf (stderr , " rodata first 8 bytes: %02x%02x%02x%02x%02x%02x%02x%02x\n" ,
453- rodata_start [0 ], rodata_start [1 ], rodata_start [2 ], rodata_start [3 ],
454- rodata_start [4 ], rodata_start [5 ], rodata_start [6 ], rodata_start [7 ]);
455- fprintf (stderr , " rodata last 8 bytes: %02x%02x%02x%02x%02x%02x%02x%02x\n" ,
456- rodata_end [-8 ], rodata_end [-7 ], rodata_end [-6 ], rodata_end [-5 ],
457- rodata_end [-4 ], rodata_end [-3 ], rodata_end [-2 ], rodata_end [-1 ]);
458- fflush (stderr );
459- }
460- #endif
461-
462336 // Per FIPS 140-3 we have to perform the CAST of the HMAC used for integrity
463337 // check before the integrity check itself. So we first call
464338 // SHA-256 and HMAC-SHA256
@@ -485,145 +359,15 @@ int BORINGSSL_integrity_test(void) {
485359#endif
486360#if defined(BORINGSSL_SHARED_LIBRARY )
487361 uint64_t length = end - start ;
488- uint64_t rodata_length = rodata_end - rodata_start ;
489362 uint8_t buffer [sizeof (length )];
490-
491- #if defined(OPENSSL_WINDOWS ) && defined(OPENSSL_AARCH64 )
492- // On ARM64 Windows, ASLR is mandatory. Undo PE base relocations in
493- // temporary copies of the FIPS sections so the hash is load-address
494- // independent. See the comment above fips_undo_base_relocations().
495- //
496- // IMPORTANT: The PE loader overwrites OptionalHeader.ImageBase in memory
497- // with the actual load address, so reading it from the in-memory PE header
498- // always gives delta==0. We must read the *original* ImageBase from the
499- // DLL file on disk to obtain the true preferred base.
500- uint8_t * text_copy = NULL ;
501- uint8_t * rodata_copy = NULL ;
502- const uint8_t * text_to_hash = start ;
503- const uint8_t * rodata_to_hash = rodata_start ;
504-
505- HMODULE fips_module = NULL ;
506- if (GetModuleHandleExW (
507- GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
508- GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT ,
509- (LPCWSTR )start , & fips_module )) {
510- const uintptr_t actual_base = (uintptr_t )fips_module ;
511-
512- // Read the preferred ImageBase from the DLL file on disk.
513- uintptr_t preferred_base = actual_base ; // fallback: assume no relocation
514- wchar_t dll_path [MAX_PATH ];
515- if (GetModuleFileNameW (fips_module , dll_path , MAX_PATH ) != 0 ) {
516- HANDLE hFile = CreateFileW (dll_path , GENERIC_READ , FILE_SHARE_READ ,
517- NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL ,
518- NULL );
519- if (hFile != INVALID_HANDLE_VALUE ) {
520- IMAGE_DOS_HEADER file_dos_header ;
521- DWORD bytes_read = 0 ;
522- if (ReadFile (hFile , & file_dos_header , sizeof (file_dos_header ),
523- & bytes_read , NULL ) &&
524- bytes_read == sizeof (file_dos_header ) &&
525- file_dos_header .e_magic == IMAGE_DOS_SIGNATURE ) {
526- LARGE_INTEGER nt_offset ;
527- nt_offset .QuadPart = file_dos_header .e_lfanew ;
528- if (SetFilePointerEx (hFile , nt_offset , NULL , FILE_BEGIN )) {
529- IMAGE_NT_HEADERS file_nt_headers ;
530- if (ReadFile (hFile , & file_nt_headers , sizeof (file_nt_headers ),
531- & bytes_read , NULL ) &&
532- bytes_read == sizeof (file_nt_headers ) &&
533- file_nt_headers .Signature == IMAGE_NT_SIGNATURE ) {
534- preferred_base =
535- (uintptr_t )file_nt_headers .OptionalHeader .ImageBase ;
536- }
537- }
538- }
539- CloseHandle (hFile );
540- }
541- }
542-
543- const intptr_t delta = (intptr_t )(actual_base - preferred_base );
544- const IMAGE_DOS_HEADER * dos_header =
545- (const IMAGE_DOS_HEADER * )fips_module ;
546- const IMAGE_NT_HEADERS * nt_headers = (const IMAGE_NT_HEADERS * )(
547- (const uint8_t * )fips_module + dos_header -> e_lfanew );
548-
549- fprintf (stderr , "FIPS reloc-undo: actual_base=%p preferred_base(file)=%p delta=0x%llx\n" ,
550- (const void * )actual_base , (const void * )preferred_base ,
551- (unsigned long long )delta );
552-
553- if (delta != 0 ) {
554- const IMAGE_DATA_DIRECTORY * reloc_dir =
555- & nt_headers -> OptionalHeader
556- .DataDirectory [IMAGE_DIRECTORY_ENTRY_BASERELOC ];
557- fprintf (stderr , "FIPS reloc-undo: reloc_dir RVA=0x%lx Size=0x%lx\n" ,
558- (unsigned long )reloc_dir -> VirtualAddress ,
559- (unsigned long )reloc_dir -> Size );
560- if (reloc_dir -> Size > 0 ) {
561- const uint8_t * reloc_table =
562- (const uint8_t * )fips_module + reloc_dir -> VirtualAddress ;
563-
564- text_copy = malloc ((size_t )length );
565- rodata_copy = malloc ((size_t )rodata_length );
566- if (text_copy != NULL && rodata_copy != NULL ) {
567- memcpy (text_copy , start , (size_t )length );
568- memcpy (rodata_copy , rodata_start , (size_t )rodata_length );
569-
570- const uintptr_t text_rva = (uintptr_t )start - actual_base ;
571- const uintptr_t rodata_rva = (uintptr_t )rodata_start - actual_base ;
572-
573- size_t text_reloc_count = 0 , rodata_reloc_count = 0 ;
574- fips_undo_base_relocations (text_copy , (size_t )length , text_rva ,
575- delta , reloc_table , reloc_dir -> Size ,
576- & text_reloc_count );
577- fips_undo_base_relocations (rodata_copy , (size_t )rodata_length ,
578- rodata_rva , delta , reloc_table ,
579- reloc_dir -> Size , & rodata_reloc_count );
580- text_to_hash = text_copy ;
581- rodata_to_hash = rodata_copy ;
582- fprintf (stderr , "FIPS reloc-undo: undid %zu text + %zu rodata relocations\n" ,
583- text_reloc_count , rodata_reloc_count );
584- fprintf (stderr , "FIPS reloc-undo: text first 8 after undo: "
585- "%02x%02x%02x%02x%02x%02x%02x%02x\n" ,
586- text_copy [0 ], text_copy [1 ], text_copy [2 ], text_copy [3 ],
587- text_copy [4 ], text_copy [5 ], text_copy [6 ], text_copy [7 ]);
588- fprintf (stderr , "FIPS reloc-undo: rodata first 8 after undo: "
589- "%02x%02x%02x%02x%02x%02x%02x%02x\n" ,
590- rodata_copy [0 ], rodata_copy [1 ], rodata_copy [2 ], rodata_copy [3 ],
591- rodata_copy [4 ], rodata_copy [5 ], rodata_copy [6 ], rodata_copy [7 ]);
592- } else {
593- fprintf (stderr , "FIPS reloc-undo: malloc failed\n" );
594- }
595- }
596- } else {
597- fprintf (stderr , "FIPS reloc-undo: delta==0, hashing directly from memory\n" );
598- }
599- } else {
600- fprintf (stderr , "FIPS reloc-undo: GetModuleHandleExW failed (err=%lu)\n" ,
601- GetLastError ());
602- }
603-
604- fprintf (stderr , "FIPS reloc-undo: hashing from %s\n" ,
605- (text_to_hash == start ) ? "MEMORY (no undo)" : "UNRELOCATED COPY" );
606- fflush (stderr );
607-
608363 CRYPTO_store_u64_le (buffer , length );
609364 HMAC_Update (& hmac_ctx , buffer , sizeof (length ));
610- HMAC_Update (& hmac_ctx , text_to_hash , ( size_t ) length );
365+ HMAC_Update (& hmac_ctx , start , length );
611366
612- CRYPTO_store_u64_le (buffer , rodata_length );
613- HMAC_Update (& hmac_ctx , buffer , sizeof (length ));
614- HMAC_Update (& hmac_ctx , rodata_to_hash , (size_t )rodata_length );
615-
616- free (text_copy );
617- free (rodata_copy );
618- #else
367+ length = rodata_end - rodata_start ;
619368 CRYPTO_store_u64_le (buffer , length );
620369 HMAC_Update (& hmac_ctx , buffer , sizeof (length ));
621- HMAC_Update (& hmac_ctx , start , (size_t )length );
622-
623- CRYPTO_store_u64_le (buffer , rodata_length );
624- HMAC_Update (& hmac_ctx , buffer , sizeof (length ));
625- HMAC_Update (& hmac_ctx , rodata_start , (size_t )rodata_length );
626- #endif // OPENSSL_WINDOWS && OPENSSL_AARCH64
370+ HMAC_Update (& hmac_ctx , rodata_start , length );
627371#else
628372 HMAC_Update (& hmac_ctx , start , end - start );
629373#endif
0 commit comments