/* grub_fatal() on error */ static grub_err_t grub_cmd_readpcr( grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { if ( argc == 0 ) { grub_fatal( "grub_cmd_readpcr: index expected" ); } if ( argc > 1 ) { grub_fatal( "grub_cmd_readpcr: Too many arguments" ); } unsigned long index = grub_strtoul( args[0], NULL, 10 ); /* if index is invalid */ if( grub_errno != GRUB_ERR_NONE ) { grub_fatal( "grub_cmd_readpcr: invalid format for index" ); } grub_uint8_t result[SHA1_DIGEST_SIZE] = { 0 }; grub_TPM_readpcr( index, &result[0] ); grub_printf( "PCR[%lu]=", index ); print_sha1( result ); grub_printf("\n"); return GRUB_ERR_NONE; }
/* grub_fatal() on error */ static void grub_TPM_readpcr( const unsigned long index, grub_uint8_t* result ) { CHECK_FOR_NULL_ARGUMENT( result ) PassThroughToTPM_InputParamBlock *passThroughInput = NULL; PCRReadIncoming* pcrReadIncoming = NULL; grub_uint16_t inputlen = sizeof( *passThroughInput ) - sizeof( passThroughInput->TPMOperandIn ) + sizeof( *pcrReadIncoming ); PassThroughToTPM_OutputParamBlock *passThroughOutput = NULL; PCRReadOutgoing* pcrReadOutgoing = NULL; grub_uint16_t outputlen = sizeof( *passThroughOutput ) - sizeof( passThroughOutput->TPMOperandOut ) + sizeof( *pcrReadOutgoing ); passThroughInput = grub_zalloc( inputlen ); if( ! passThroughInput ) { grub_fatal( "readpcr: memory allocation failed" ); } passThroughInput->IPBLength = inputlen; passThroughInput->OPBLength = outputlen; pcrReadIncoming = (void *)passThroughInput->TPMOperandIn; pcrReadIncoming->tag = grub_swap_bytes16_compile_time( TPM_TAG_RQU_COMMAND ); pcrReadIncoming->paramSize = grub_swap_bytes32( sizeof( *pcrReadIncoming ) ); pcrReadIncoming->ordinal = grub_swap_bytes32_compile_time( TPM_ORD_PcrRead ); pcrReadIncoming->pcrIndex = grub_swap_bytes32( (grub_uint32_t) index); passThroughOutput = grub_zalloc( outputlen ); if( ! passThroughOutput ) { grub_free( passThroughInput ); grub_fatal( "readpcr: memory allocation failed" ); } grub_TPM_int1A_passThroughToTPM( passThroughInput, passThroughOutput ); grub_free( passThroughInput ); pcrReadOutgoing = (void *)passThroughOutput->TPMOperandOut; grub_uint32_t tpm_PCRreadReturnCode = grub_swap_bytes32( pcrReadOutgoing->returnCode ); if( tpm_PCRreadReturnCode != TPM_SUCCESS ) { grub_free( passThroughOutput ); if( tpm_PCRreadReturnCode == TPM_BADINDEX ) { grub_fatal( "readpcr: bad pcr index" ); } grub_fatal( "readpcr: tpm_PCRreadReturnCode: %u", tpm_PCRreadReturnCode ); } grub_memcpy( result, pcrReadOutgoing->pcr_value, SHA1_DIGEST_SIZE ); grub_free( passThroughOutput ); }
volatile void * grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), grub_addr_t base, grub_size_t size) { int i; grub_addr_t newbase; /* First try already used registers. */ for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) if (usage_win[i] && base_win[i] <= base && base_win[i] + sizes_win[i] > base + size) { usage_win[i]++; return (void *) (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); } /* Map new register. */ newbase = base & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK; for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) if (!usage_win[i] && newbase <= base && newbase + sizes_win[i] > base + size) { usage_win[i]++; base_win[i] = newbase; write_bases (); return (void *) (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); } grub_fatal ("Out of PCI windows."); }
void grub_tsc_init (void) { if (!grub_cpu_is_tsc_supported ()) { #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_IEEE1275) grub_install_get_time_ms (grub_rtc_get_time_ms); #else grub_fatal ("no TSC found"); #endif return; } tsc_boot_time = grub_get_tsc (); #ifdef GRUB_MACHINE_XEN (void) (grub_tsc_calibrate_from_xen () || calibrate_tsc_hardcode()); #elif defined (GRUB_MACHINE_EFI) (void) (grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode()); #elif defined (GRUB_MACHINE_COREBOOT) (void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode()); #else (void) (grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode()); #endif grub_install_get_time_ms (grub_tsc_get_time_ms); }
/* grub_fatal() on error */ static grub_err_t grub_cmd_measure( grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { if ( argc != 2 ) { grub_fatal( "Wrong number of arguments" ); } unsigned long index = grub_strtoul( args[1], NULL, 10 ); /* if index is invalid */ if( grub_errno != GRUB_ERR_NONE ) { grub_fatal( "invalid format for index" ); } grub_TPM_measure_file( args[0], index ); return GRUB_ERR_NONE; }
static int panic (lua_State *L) { (void)L; /* to avoid warnings */ #if 0 fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1)); #else grub_fatal ("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1)); #endif return 0; }
/* grub_fatal() on error */ static grub_err_t grub_cmd_tcglog( grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { if ( argc == 0 ) { grub_fatal( "grub_cmd_tcglog: index expected" ); } if ( argc > 1 ) { grub_fatal( "grub_cmd_tcglog: Too many arguments" ); } unsigned long index = grub_strtoul( args[0], NULL, 10 ); /* if index is invalid */ if( grub_errno != GRUB_ERR_NONE ) { grub_fatal( "grub_cmd_tcglog: invalid format for index" ); } grub_TPM_read_tcglog( index ) ; return GRUB_ERR_NONE; }
grub_err_t grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t, void *), void *hook_data) { grub_linuxbios_table_header_t table_header; grub_linuxbios_table_item_t table_item; /* Assuming table_header is aligned to its size (8 bytes). */ for (table_header = (grub_linuxbios_table_header_t) 0x500; table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++) if (check_signature (table_header)) goto signature_found; for (table_header = (grub_linuxbios_table_header_t) 0xf0000; table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++) if (check_signature (table_header)) goto signature_found; grub_fatal ("Could not find coreboot table\n"); signature_found: table_item = (grub_linuxbios_table_item_t) ((char *) table_header + table_header->header_size); for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header + table_header->header_size + table_header->table_size); table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size)) { if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK && check_signature ((grub_linuxbios_table_header_t) (grub_addr_t) *(grub_uint64_t *) (table_item + 1))) { table_header = (grub_linuxbios_table_header_t) (grub_addr_t) *(grub_uint64_t *) (table_item + 1); goto signature_found; } if (hook (table_item, hook_data)) return 1; } return 0; }
void grub_arch_sync_caches (void *address, grub_size_t len) { grub_size_t start, end, max_align; if (dlinesz == 0) probe_caches(); if (dlinesz == 0) grub_fatal ("Unknown cache line size!"); max_align = dlinesz > ilinesz ? dlinesz : ilinesz; start = ALIGN_DOWN ((grub_size_t) address, max_align); end = ALIGN_UP ((grub_size_t) address + len, max_align); grub_arch_clean_dcache_range (start, end, dlinesz); grub_arch_invalidate_icache_range (start, end, ilinesz); }
/* Load all modules in core. */ static void grub_load_modules (void) { auto int hook (struct grub_module_header *); int hook (struct grub_module_header *header) { /* Not an ELF module, skip. */ if (header->type != OBJ_TYPE_ELF) return 0; if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header), (header->size - sizeof (struct grub_module_header)))) grub_fatal ("%s", grub_errmsg); if (grub_errno) grub_print_error (); return 0; } grub_module_iterate (hook); }
/* Find the optimal number of pages for the memory map. Is it better to move this code to efi/mm.c? */ static grub_efi_uintn_t find_efi_mmap_size (void) { static grub_efi_uintn_t mmap_size = 0; if (mmap_size != 0) return mmap_size; mmap_size = (1 << 12); while (1) { int ret; grub_efi_memory_descriptor_t *mmap; grub_efi_uintn_t desc_size; mmap = grub_malloc (mmap_size); if (! mmap) return 0; ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); grub_free (mmap); if (ret < 0) grub_fatal ("cannot get memory map"); else if (ret > 0) break; mmap_size += (1 << 12); } /* Increase the size a bit for safety, because GRUB allocates more on later, and EFI itself may allocate more. */ mmap_size += (1 << 12); mmap_size = page_align (mmap_size); return mmap_size; }
__attribute__((noreturn)) void exit(int status) { grub_fatal("Internal error: Python tried to exit with status %d\n", status); }
void _assert(const char *filename, unsigned line, int condition, const char *condition_str) { if (!condition) grub_fatal("%s:%u: Python assertion failure: assert(%s)\n", filename, line, condition_str); }
grub_uint32_t grub_get_rtc (void) { grub_fatal ("grub_get_rtc() is not implemented.\n"); }
/**************** * RES = BASE ^ EXPO mod MOD */ void gcry_mpi_powm (gcry_mpi_t res, gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod) { /* Pointer to the limbs of the arguments, their size and signs. */ mpi_ptr_t rp, ep, mp, bp; mpi_size_t esize, msize, bsize, rsize; int msign, bsign, rsign; /* Flags telling the secure allocation status of the arguments. */ int esec, msec, bsec; /* Size of the result including space for temporary values. */ mpi_size_t size; /* Helper. */ int mod_shift_cnt; int negative_result; mpi_ptr_t mp_marker = NULL; mpi_ptr_t bp_marker = NULL; mpi_ptr_t ep_marker = NULL; mpi_ptr_t xp_marker = NULL; unsigned int mp_nlimbs = 0; unsigned int bp_nlimbs = 0; unsigned int ep_nlimbs = 0; unsigned int xp_nlimbs = 0; mpi_ptr_t tspace = NULL; mpi_size_t tsize = 0; esize = expo->nlimbs; msize = mod->nlimbs; size = 2 * msize; msign = mod->sign; esec = mpi_is_secure(expo); msec = mpi_is_secure(mod); bsec = mpi_is_secure(base); rp = res->d; ep = expo->d; if (!msize) grub_fatal ("mpi division by zero"); if (!esize) { /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 depending on if MOD equals 1. */ res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; if (res->nlimbs) { RESIZE_IF_NEEDED (res, 1); rp = res->d; rp[0] = 1; } res->sign = 0; goto leave; } /* Normalize MOD (i.e. make its most significant bit set) as required by mpn_divrem. This will make the intermediate values in the calculation slightly larger, but the correct result is obtained after a final reduction using the original MOD value. */ mp_nlimbs = msec? msize:0; mp = mp_marker = mpi_alloc_limb_space(msize, msec); count_leading_zeros (mod_shift_cnt, mod->d[msize-1]); if (mod_shift_cnt) _gcry_mpih_lshift (mp, mod->d, msize, mod_shift_cnt); else MPN_COPY( mp, mod->d, msize ); bsize = base->nlimbs; bsign = base->sign; if (bsize > msize) { /* The base is larger than the module. Reduce it. Allocate (BSIZE + 1) with space for remainder and quotient. (The quotient is (bsize - msize + 1) limbs.) */ bp_nlimbs = bsec ? (bsize + 1):0; bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); MPN_COPY ( bp, base->d, bsize ); /* We don't care about the quotient, store it above the * remainder, at BP + MSIZE. */ _gcry_mpih_divrem( bp + msize, 0, bp, bsize, mp, msize ); bsize = msize; /* Canonicalize the base, since we are going to multiply with it quite a few times. */ MPN_NORMALIZE( bp, bsize ); } else bp = base->d; if (!bsize) { res->nlimbs = 0; res->sign = 0; goto leave; } /* Make BASE, EXPO and MOD not overlap with RES. */ if ( rp == bp ) { /* RES and BASE are identical. Allocate temp. space for BASE. */ gcry_assert (!bp_marker); bp_nlimbs = bsec? bsize:0; bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); MPN_COPY(bp, rp, bsize); } if ( rp == ep ) { /* RES and EXPO are identical. Allocate temp. space for EXPO. */ ep_nlimbs = esec? esize:0; ep = ep_marker = mpi_alloc_limb_space( esize, esec ); MPN_COPY(ep, rp, esize); } if ( rp == mp ) { /* RES and MOD are identical. Allocate temporary space for MOD.*/ gcry_assert (!mp_marker); mp_nlimbs = msec?msize:0; mp = mp_marker = mpi_alloc_limb_space( msize, msec ); MPN_COPY(mp, rp, msize); } /* Copy base to the result. */ if (res->alloced < size) { mpi_resize (res, size); rp = res->d; } MPN_COPY ( rp, bp, bsize ); rsize = bsize; rsign = bsign; /* Main processing. */ { mpi_size_t i; mpi_ptr_t xp; int c; mpi_limb_t e; mpi_limb_t carry_limb; struct karatsuba_ctx karactx; xp_nlimbs = msec? (2 * (msize + 1)):0; xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); memset( &karactx, 0, sizeof karactx ); negative_result = (ep[0] & 1) && base->sign; i = esize - 1; e = ep[i]; count_leading_zeros (c, e); e = (e << c) << 1; /* Shift the expo bits to the left, lose msb. */ c = BITS_PER_MPI_LIMB - 1 - c; /* Main loop. Make the result be pointed to alternately by XP and RP. This helps us avoid block copying, which would otherwise be necessary with the overlap restrictions of _gcry_mpih_divmod. With 50% probability the result after this loop will be in the area originally pointed by RP (==RES->d), and with 50% probability in the area originally pointed to by XP. */ for (;;) { while (c) { mpi_ptr_t tp; mpi_size_t xsize; /*mpih_mul_n(xp, rp, rp, rsize);*/ if ( rsize < KARATSUBA_THRESHOLD ) _gcry_mpih_sqr_n_basecase( xp, rp, rsize ); else { if ( !tspace ) { tsize = 2 * rsize; tspace = mpi_alloc_limb_space( tsize, 0 ); } else if ( tsize < (2*rsize) ) { _gcry_mpi_free_limb_space (tspace, 0); tsize = 2 * rsize; tspace = mpi_alloc_limb_space (tsize, 0 ); } _gcry_mpih_sqr_n (xp, rp, rsize, tspace); } xsize = 2 * rsize; if ( xsize > msize ) { _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); xsize = msize; } tp = rp; rp = xp; xp = tp; rsize = xsize; /* To mitigate the Yarom/Falkner flush+reload cache * side-channel attack on the RSA secret exponent, we do * the multiplication regardless of the value of the * high-bit of E. But to avoid this performance penalty * we do it only if the exponent has been stored in secure * memory and we can thus assume it is a secret exponent. */ if (esec || (mpi_limb_signed_t)e < 0) { /*mpih_mul( xp, rp, rsize, bp, bsize );*/ if( bsize < KARATSUBA_THRESHOLD ) _gcry_mpih_mul ( xp, rp, rsize, bp, bsize ); else _gcry_mpih_mul_karatsuba_case (xp, rp, rsize, bp, bsize, &karactx); xsize = rsize + bsize; if ( xsize > msize ) { _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); xsize = msize; } } if ( (mpi_limb_signed_t)e < 0 ) { tp = rp; rp = xp; xp = tp; rsize = xsize; } e <<= 1; c--; } i--; if ( i < 0 ) break; e = ep[i]; c = BITS_PER_MPI_LIMB; } /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT steps. Adjust the result by reducing it with the original MOD. Also make sure the result is put in RES->d (where it already might be, see above). */ if ( mod_shift_cnt ) { carry_limb = _gcry_mpih_lshift( res->d, rp, rsize, mod_shift_cnt); rp = res->d; if ( carry_limb ) { rp[rsize] = carry_limb; rsize++; } } else if (res->d != rp) { MPN_COPY (res->d, rp, rsize); rp = res->d; } if ( rsize >= msize ) { _gcry_mpih_divrem(rp + msize, 0, rp, rsize, mp, msize); rsize = msize; } /* Remove any leading zero words from the result. */ if ( mod_shift_cnt ) _gcry_mpih_rshift( rp, rp, rsize, mod_shift_cnt); MPN_NORMALIZE (rp, rsize); _gcry_mpih_release_karatsuba_ctx (&karactx ); } /* Fixup for negative results. */ if ( negative_result && rsize ) { if ( mod_shift_cnt ) _gcry_mpih_rshift( mp, mp, msize, mod_shift_cnt); _gcry_mpih_sub( rp, mp, msize, rp, rsize); rsize = msize; rsign = msign; MPN_NORMALIZE(rp, rsize); } gcry_assert (res->d == rp); res->nlimbs = rsize; res->sign = rsign; leave: if (mp_marker) _gcry_mpi_free_limb_space( mp_marker, mp_nlimbs ); if (bp_marker) _gcry_mpi_free_limb_space( bp_marker, bp_nlimbs ); if (ep_marker) _gcry_mpi_free_limb_space( ep_marker, ep_nlimbs ); if (xp_marker) _gcry_mpi_free_limb_space( xp_marker, xp_nlimbs ); if (tspace) _gcry_mpi_free_limb_space( tspace, 0 ); }
void grub_machine_init (void) { int i; int grub_lower_mem; /* Initialize the console as early as possible. */ grub_console_init (); grub_lower_mem = grub_get_conv_memsize () << 10; /* Sanity check. */ if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END) grub_fatal ("too small memory"); /* FIXME: This prevents loader/i386/linux.c from using low memory. When our heap implements support for requesting a chunk in low memory, this should no longer be a problem. */ #if 0 /* Add the lower memory into free memory. */ if (grub_lower_mem >= GRUB_MEMORY_MACHINE_RESERVED_END) add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END, grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END); #endif auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type) { /* Avoid the lower memory. */ if (addr < 0x100000) { if (size <= 0x100000 - addr) return 0; size -= 0x100000 - addr; addr = 0x100000; } /* Ignore >4GB. */ if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) { grub_size_t len; len = (grub_size_t) ((addr + size > 0xFFFFFFFF) ? 0xFFFFFFFF - addr : size); add_mem_region (addr, len); } return 0; } grub_machine_mmap_iterate (hook); compact_mem_regions (); for (i = 0; i < num_regions; i++) grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size); grub_tsc_init (); }
__attribute__((noreturn)) void abort(void) { grub_fatal("Internal error: Python called abort()\n"); }
/* grub_fatal() on error */ static void grub_TPM_read_tcglog( const unsigned long index ) { grub_uint32_t returnCode, featureFlags, eventLog = 0, logAddr = 0, edi = 0; grub_uint8_t major, minor; /* get event log pointer */ grub_TPM_int1A_statusCheck( &returnCode, &major, &minor, &featureFlags, &eventLog, &edi ); /* edi = 0 means event log is empty */ if( edi == 0 ) { grub_fatal( "Event log is empty" ); } logAddr = eventLog; TCG_PCClientPCREvent *event = NULL; /* index = 0: print all entries */ if ( index == 0 ) { /* eventLog = absolute pointer to the beginning of the event log. */ event = (TCG_PCClientPCREvent *) logAddr; /* If there is exactly one entry */ if( edi == eventLog ) { grub_printf( "pcrIndex: %u \n", event->pcrIndex ); grub_printf( "eventType: %u \n", event->eventType ); grub_printf( "digest: " ); print_sha1( event->digest ); grub_printf( "\n\n" ); } else { /* If there is more than one entry */ do { grub_printf( "pcrIndex: %u \n", event->pcrIndex ); grub_printf( "eventType: %u \n", event->eventType ); grub_printf( "digest: " ); print_sha1( event->digest ); grub_printf( "\n\n" ); logAddr += TCG_PCR_EVENT_SIZE + event->eventDataSize; event = (TCG_PCClientPCREvent *)logAddr; } while( logAddr != edi ); /* print the last one */ grub_printf( "pcrIndex: %u \n", event->pcrIndex ); grub_printf( "eventType: %u \n", event->eventType ); grub_printf( "digest: " ); print_sha1( event->digest ); grub_printf( "\n\n" ); } } else { /* print specific entry */ logAddr = eventLog; unsigned long i; for( i = 1; i < index; i++ ) { event = (TCG_PCClientPCREvent *)logAddr; logAddr += TCG_PCR_EVENT_SIZE + event->eventDataSize; if( logAddr > edi ) { /* index not valid. */ grub_fatal( "No entry at specified index" ); } } event = (TCG_PCClientPCREvent *)logAddr; grub_printf( "pcrIndex: %u \n", event->pcrIndex ); grub_printf( "eventType: %u \n", event->eventType ); grub_printf( "digest: " ); print_sha1( event->digest ); grub_printf( "\n\n" ); } }