Giter VIP home page Giter VIP logo

heads-wiki's Introduction

heads-wiki's People

Contributors

alexgithublab avatar b068931cc450442b63f5b3d276ea4297 avatar ciaby avatar dan2468 avatar daringer avatar flammit avatar ivuk avatar jfrederickson avatar jonathonhall-purism avatar jpouellet avatar jtmoree-github-com avatar lsafd avatar merge avatar mrchromebox avatar mutablescutoid avatar natterangell avatar nemanjan00 avatar nomenkai avatar ophilli avatar orangecms avatar osresearch avatar paulmenzel avatar qqubes avatar samcday avatar saper avatar theplexus avatar thrilleratplay avatar tlaurion avatar tonux599 avatar trickv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

heads-wiki's Issues

Add glossary

Many of the terms in Heads can quickly become confusing, example "key".

Modify misleading ACM doc section of the wiki

https://matrix.to/#/!pAlHOfxQNPXOgFGTmo:matrix.org/$UAIdfkhhtYR47KGUz0bN-rnN6RmKmsAHLS-8ajHqF2k?via=matrix.org&via=nitro.chat&via=fairydust.space

https://osresearch.net/Keys/#management-engine-and-bootguard-acm-fuses states:

The x230 Thinkpads do not support bootguard and only the Librem laptops ship with unfused keys.

This misleading and untrue.

  • TXT is supported on Heads supported ThinkPads.
  • But ACM blobs are non-redistributable and would require xx30 and xx20 blobs-extract scripts to extract those blobs from proprietary firmware and then reinject them in the ROM after build time.

Reality is that no such documentation existed at the moment of writing that page, and lack of personal interest didn't lead me to them.

But that could change with community contributions, with boards that of course would not be CI built, and without roms being redistributable, unless proven otherwise.

document kexec-boot

I am studying kexec-boot to create documentation for it with an eye on fixing my own system. I'm reading source but still new to heads and not understanding everything. Hoping an issue here will get some feedback to speed up my work. Will make a pull request when I have something significant done.

I have cloned heads and heads-wiki. Currently working on adding -h to kexec-boot with descriptions of params. Can someone explain how -a and -r work? Well I see how they work but don't understand what they are trying to do? esp. '-r'

Document kgpe-d16 usage and boards options

Things are scattered around. Some drops.

Insurgo decided to fund KGPE-D16 upstreaming efforts. Donations welcome over open collective.

EDIT:

Failed to build gcc-5.3.0

When running make, I get this error. What went wrong? I'm running Debian 9.9 under Windows Subsystem for Linux.

You can now run IASL ACPI compiler from /root/heads/build/coreboot-4.8.1/util/crossgcc/xgcc.
make[2]: Leaving directory '/root/heads/build/coreboot-4.8.1'
#echo '******* Building crossgcc-arm (this might take a while) ******'
#/root/heads/build/make-4.2.1/make -C "/root/heads/build/coreboot-4.8.1" crossgcc-arm
2019-08-16 12:07:50+02:00 CONFIG coreboot
git clone https://github.com/GregorR/musl-cross "/root/heads/build/musl-cross-git"
Cloning into '/root/heads/build/musl-cross-git'...
remote: Enumerating objects: 796, done.
remote: Total 796 (delta 0), reused 0 (delta 0), pack-reused 796
Receiving objects: 100% (796/796), 289.34 KiB | 158.00 KiB/s, done.
Resolving deltas: 100% (499/499), done.
cd /root/heads/build/musl-cross-git && git submodule update --init --checkout
if [ -r patches/musl-cross.patch ]; then ( cd /root/heads/build/musl-cross-git ; patch -p1 ) < patches/musl-cross.patch || exit 1 ; fi
patching file config.sh
if [ -d patches/musl-cross ] && [ -r patches/musl-cross ] ; then for patch in patches/musl-cross/*.patch ; do echo "Applying patch file : $patch " ; ( cd /root/heads/build/musl-cross-git ; patch -p1 ) < $patch || exit 1 ; done ; fi
2019-08-16 12:08:16+02:00 CONFIG musl-cross
2019-08-16 12:08:16+02:00 MAKE musl-cross
tail /root/heads/build/log/musl-cross.log
-----
config.status: executing libtool commands
configure: summary of build options:

  Version:           GNU MP 6.1.0
  Host type:         none-unknown-linux-gnu
  ABI:               standard
  Install prefix:    /root/heads/crossgcc/x86_64-linux-musl
  Compiler:          gcc
  Static libraries:  yes
  Shared libraries:  no

make[4]: Leaving directory '/root/heads/build/musl-cross-git/gcc-5.3.0/build1'
make[3]: *** [Makefile:859: all] Error 2
make[3]: Leaving directory '/root/heads/build/musl-cross-git/gcc-5.3.0/build1'
+ die Failed to build gcc-5.3.0
+ echo Failed to build gcc-5.3.0
Failed to build gcc-5.3.0
+ exit 1
make[2]: *** [Makefile:2: ../../crossgcc/x86_64-linux-musl/bin/x86_64-musl-linux-gcc] Error 1
make[2]: Leaving directory '/root/heads/build/musl-cross-git'
make[1]: *** [Makefile:378: /root/heads/build/musl-cross-git/.build] Error 1
make[1]: Leaving directory '/root/heads'
Makefile:584: recipe for target 'all' failed
make: *** [all] Error 2
root@LAPTOP:~/heads#

Clarify and reuse proper LUKS keys terminology consistenty in doc

The keys page (https://osresearch.net/Keys/) lists 4 keys related to disks but the docs include 10 different terms.

officially listed related to drive/disk

  • TPM disk encryption key
  • Disk recovery key
  • LUKS disk encryption key
  • Disk Unlock Key passphrase prompt output

terms used in docs

TPM disk encryption key:

  • keys.md =>1
  • configuring-keys.md: => 1

Disk recovery Key:

  • keys.md => 4
  • install-os => 4

LUKS disk encryption key:

  • keys.md => 1

Disk encryption key without explicit LUKS/TPM:

  • keys.md => 4
  • upgrading.md => 1

Disk encryption recovery key:

  • upgradigng.md => 1

Disk Key:

  • faq.md => 2
  • install-os.md => 1
  • upgrading.md => 2

TPM disk unlock key:

  • keys.md => 1
  • install-os.md => 1

Disk unlock key passphrase:

  • keys.md => 3

Disk unlock key:

  • keys.md => 4
  • install-os.md => 4

TPM sealed drive keys:

  • heads-threat-model.md => 1

JT changes

After I worked on the docs it is mostly the same but a few changed

TPM disk encryption key: SAME

Disk recovery Key:

  • keys.md => same
  • install-os => same
  • upgrading.md => 2

LUKS disk encryption key: SAME

Disk encryption key without explicit LUKS/TPM:

  • keys.md => SAME
  • configuring-keys.md => SAME
  • upgrading.md => 0

Disk encryption recovery key: NONE

Disk Key:

  • faq.md => same
  • install-os.md => same
  • upgrading.md => 1 (was 2)

TPM disk unlock key: SAME

Disk unlock key passphrase:

  • keys.md => same
  • upgrading.md => 1

Disk unlock key:

  • keys.md => SAME
  • install-os.md => SAME
  • recoveryshellmd => 1
  • upgrading.md => 1

TPM sealed drive keys: SAME

@tlaurion Which of the listed keys in keys.md should be mentioned in the paragraph in upgrading.md? If the keys that should be mentioned are not listed in keys.md I will add as part of this change.

Originally posted by @jtmoree-github-com in #71 (comment)

Notes on bumping kernels and coreboot to newer versions (or how to keep xx30-flash and legacy boards alive)

Should be under heads-wiki PR, but just wanted to dump it here first to empty my mind of the process I've been through recently.

Upgrading kernel/coreboot versions is somewhat a hassle. That is, when bumping one kernel version to another, just hoping that kept in tree saveddefconfig file under config/linux-board.config will just magically produce a small, minimal kernel simply doesn't work. In fact, the savedefconfig (defconfig) file kept in tree is just the deviation to the normal defconfig for a specific version. Each time a new coreboot/kernel version sees the light, it also comes with its own defconfig.

In the case of kernel defconfig, this means new settings being activated as modules and added in kernel by default.

So here is a couple of tricks I came with in the last years to facilitate others to also do this task, taking by example the actual 4.14 kernel used currently that is wished to be bumped to 5.10.4 for a while. For the community boards, that means two kernel configs to update: linux-x230.config (shared across all boards) and linux-x230-flash.config (being aimed at being really small, used in xx30-flash boards to accomplish internal flashing of their normal legacy roms counterpart which needs to have coreboot+kernel+modules fit under 4Mb SPI flash).

So basic steps, taking the x230-flash board as an example, taking for granted heads was cloned into ~/, so ~/heads and we are by default under ~/heads:

  • Build for old version already in tree: make BOARD=x230-flash
  • We will do a hardlinked copy (playable backup at no cost) of the linux build into another directory we want to experiment in: cp -rl ~/heads/build/linux-4.14.62/ ~/heads/build/linux-4.14.62-rl
  • We copy the actual defconfig linux-x230-flash.config over hardlinked linux build directory: cp ~/heads/config/linux-x230-flash.config ~/heads/build/linux-4.14.62-rl/.config
  • We go inside of the hardlinked linux build directory: cd ~/heads/build/linux-4.14.62-rl/
  • We expend the configuration file so that we finally know what the deviation to default means for that kernel version: make menuconfig
  • We save the changes there. Exit and save. We now have the full config file under ~/heads/build/linux-4.14.62-rl/.config
  • We change the kernel version under the board config board/x230-flash/x230-flash.config being 4.14.62 to 5.10.4
  • We rebuild x230-flash so that the new kernel is downloaded, patched and extracted: cd ~/heads/ && make BOARD=x230-flash
  • We do a hardlinked copy of the newly extracted build directory so that we can play with it without touching the real linux build dir: cp -rl ~/heads/build/linux-5.10.4 ~/heads/build/linux-5.10.4-hl
  • We copy the expended config of old kernel config over : cp ~/heads/build/linux-4.14.62-rl/.config ~/heads/build/linux-5.10.4-hl/.config
  • We go inside that new kernel build directory: cd ~/heads/build/linux-5.10.4-hl/
  • We generate a new complete configuration based on 4.14.62 full kernel config: make menuconfig. Exit and save.
  • We take a copy of that "ported" 4.14.64 to 5.10.4 config to keep track of what we tuned: cp ~/heads/build/linux-5.10.4-hl/.config ~/heads/build/linux-5.10.4-hl/.config_ported_from_4.14.64
  • We can now compare all the new stuff between the old and new kernel added defaults: meld/diff/whatever ~/heads/build/linux-4.14.62-rl/.config ~/heads/build/linux-5.10.4-hl/.config
  • If we change the settings manually under ~/heads/build/linux-5.10.4-hl/.config,We make sure those are kept by a make menuconfig under that directory, and we review the changes. It is important to understand dependencies between Kconfig options. This website helps a lot: https://www.kernelconfig.io
  • We compare the changes we enforced did since the beginning of the tuning effort: diff/meld/whatever ~/heads/build/linux-5.10.4-hl/.config ~/heads/build/linux-5.10.4-hl/.config_ported_from_4.14.64
  • We keep track of interesting changes we were able to be kept saved after a make menuconfig: cp ~/heads/build/linux-5.10.4-hl/.config ~/heads/build/linux-5.10.4-hl/.config_removed_networking-debug_symbols-unused_crypto_digests
  • When we are ready to test the changes, we copy over the working copy of .config file to what the build system expects to use for a board build: cp ~/heads/build/linux-5.10.4-hl/.config ~/heads/config/linux-x230-flash.config
  • We rebuild the board: cd ~/heads && make BOARD=x230-flash and we cross fingers that all the build process will succeed into creating a small enough kernel to fit for the xx30-flash board config.
  • When we are successful and the new board produced ROM boots (HURRAY!) we go back to our hardlinked linux build dir: cd ~/heads/build/linux-5.10.4-hl/
  • We create a defconfig: make savedefconfig
  • We copy it over where heads build system feeds on it: cp ~/heads/build/linux-5.10.4-hl/defconfig ~/heads/config/linux-x230-flash.config
  • Then we redo the process for linux-x230.config!
  • When all is good, we create a PR taking all the files we touched (includes all the board configs, linux-x230-flash.config, linux-x230.config, maybe modules/linux changes)
  • We ask for review, and we debate what is really needed and what is not, since everything constantly changes in coreboot/kernel configs.

As a sidenote, I might start soon to redistribute full linux configurations as opposed to defconfig versions, as it once was under Heads repo, at least for linux configurations. This is way more clear, IMOH to see what we do not want (for the eyes) to make sure everything else in the same category in full config changes would need to be deactivated as well. Otherwise it is so easy to have AMD related Kconfig options on Intel based systems, have Network interface support included in the kernel boosting its size etc.

Document where to find/download latest CircleCI builds


End-users:

  • CircleCI builds for each accepted change. In Github/Git terms, that means, for each commit pushed in the project. So all accepted commits are here: https://github.com/osresearch/heads/commits/master

  • CircleCI also builds Pull Requests (PR). The same logic below applies to PR, but you will see the red/green mark in the PR itself. Clicking green marks will bring you to downloadable artifacts for a board, including ROMs.


Code contributors:

  • If you are the owner of a PR, it is highly suggested to login on CircleCI and have CircleCI follow your own Heads reprository. That way, each time you push a commit, CircleCI will build all the boards on your own time. You will also be the owner of your own CircleCI instance, meaning that if for whatever reason, you need to kick a stalled build, you will be able to from CircleCI.

For commits pushed together, you will see a red X (for builds that failed) and a green mark for builds that were successful.

To access a build ROM for a specific board, taking x230-htop-maximized as an example:

  • Click latest green mark at https://github.com/osresearch/heads/commits/master and note the Commit ID (7 characters hexadecimal value, which will be in the name of the ROM you will download later)
  • This opens the list of boards for which ROMs have been built. Click on a board name "details" ( here x230-hotp-maximized ). This brings you to CircleCI for a specific "Job" (which is the board build you selected).
  • Click on the "Make board" Open in a Tab link. This opens the build log for that board builld, where the last lines there show the sha256sum hashes of the ROM(s) that have been built fro that board.
  • Click the Artifacts tab (Artifacts are kept results for 30 days, including logs, ROMs, hashes etc)
  • Right-click a ROM, save as.. and decide where you want to keep it. We take for granted here that it is in the Downloads directory of the current qubes (Depending of browsers's internals, some will open the ROMs as text. We do not want that which is why "Save as..." is suggested.

To verify hashes:

  • Open a Terminal in the same qube the rom was downloaded from.
    • Type sha256sum ~/Downloads/heads-x230-hotp-maximized*
    • Compare the hash value you get at the console from what was obtained from the "Make board" tab you opened earlier. They should match.

To copy that rom to a USB thumb drive:

  • On that same terminal, qvm-copy ~/Downloads/heads-x230-hotp-maximized* and select sys-usb.
  • Open Files application on sys-usb qubes.
    • Plug your formatted ext3/ext4 thumb drive. Mount it. Go to your Home directory, click QubesIncoming, select the qubes directory name from which you copied the rom from. Move the rom image on your USB thumb drive. Eject the device.

Flashing instructions depends of what you current running firmware is. If you already run a Maximized rom, you can upgrade the firmware from the Graphical Interface. Otherwise, please refer to https://osresearch.net/Prerequisites#legacy-vs-maximized-boards. Basic instructions are below, but only proceed if you are sure what you are doing, otherwise a brick could occur.


What to download:
For maximized boards already flashed externally:

  • Download the non top/bottom rom.

For maximized board non already flashed externally:

  • Download top + bottom rom files and flash externally.

For the PrivacyBeast (and other KNOWN TO BE UNLOCKED IFD AND UNLUCKED ME regions on initial external flashing of bottom SPI ( or those having followed https://osresearch.net/Clean-the-ME-firmware/):

  • Download non top/bottom rom (12mb rom image)
  • DO NOT USE HEADS FLASH MENU TO FLASH INTERNALLY INITIAL MAXIMIZED ROM. Instead:
    • From recovery shell:
      • mount-usb
      • sha256sum /media/ADDITIONAL_PATH_TO/heads-xx30-hotp-maximized-12mb.rom (Double verify that the hash corresponds to the hash of the file you downloaded. If different, do not proceed)
      • flashrom --force --noverify-all -p internal -w /media/ADDITIONAL_PATH_TO/heads-xx30-hotp-maximized-12mb.rom

For non maximized board (legacy) non already flashed externally

  • Consider using maximized boards (and external initial flashing of SPI chip(s)!)
  • If initial flashing is not possible:
    • Download corresponding board flash board's ROM (x230-flash, t430-flash) and flash externally (1vyrain too...)
    • Download corresponding board ROM (x230/t430, x230/t430-hotp-verification) (applies to skulls->heads upgrade)

Comments/Help welcome to turn this into a PR.

T530/w530 disassembling/flashing notes

@eganonoa wrote : "Note: it can be tricky to properly read the 8MB chip on the T530 and W530 (see #996). This appears to be because the two chips share a power source on these boards (see generally). This is true for both the Rasbperry Pi and the CH431a. There appears to be two workarounds: (1) the Wake on Lan method (which has the one downside of only working once, because it is not supported by coreboot and is, therefore, not available after flashing); or (2) keeping the CMOS battery plugged in, which works also post-flashing. Both methods provide a little extra power to the board and appear to then be sufficient to get enough power to the 8MB chip to get a proper read of it. The Skulls team generally suggest using an external power source with the CH341a, and it's possible that this might help, but I have not tested."

From linuxboot/heads#1072 (comment)

This needs to be documented properly

Update write protection docs after testing

https://osresearch.net/Heads-threat-model/#write-protecting-the-bios-chip-advanced

Write protection could be applied today with Nlnet funded related work inside of dasharo/flashrom, to protect at least coreboot's bootblock region.

But from current documentation, bootblock being near the end of CBFS, but not at a fixed area is problematic for internal firmware upgrades, locking 64kb of space that could lead to brick if coreboot version upgrades are to be applied.

To be tested and documentation at least referred for people willing to sacrifice internal flashing of Heads when a coreboot version bump touching bootblock changes occurred (still untested on my side).

To be addressed when dasharo/flashrom includes kgpe-d16 ast1000 support, currently missing so that flashrom used under Heads is not causing any regression.

iasl is necessary for edk2 build

For building the BOARD=qemu-linuxboot target, the iasl compiler is necessary. This duplicates the one that we build as part of coreboot and potentially introduces irreproducibility.

busybox is not reproducible

busybox difference between 2 debian-10 hosts with different paths of builds is too big to output here.

mainly, time of compilation is injected, all address of code is shifted, including entry point.

Originally posted by @tlaurion in #70 (comment)

"no agent running" when attempting to configure PGP key

So I'm up to "Adding your PGP key" after going through the previous steps in the Installing Heads tutorial. I boot into the recovery shell fine, but after running mount-usb which seems to require me to run mount -o remount,rw /media for some reason as it gets mounted as read only, and then running gpg --homedir=/media/gnupg/ --card-edit, I'm getting the error "OpenPGP card not available: No agent running" -- but when running gpg-agent it says there is one running. I've followed all the previous steps to a tee and have both the USB drive and the (new) Yubikey inserted. Is there a step I'm missing?

Not able to sign into Slack with gmail account.

I tried to register to the Open Source Firmware Slack channel using a gmail account. When trying to "Connect with Google", I am sent a verification for my 2FA but will say that my email and password are not valid. The only a google.com domain email address can be used when creating an account. There is a message that says

Donโ€™t have an @google.com email address?
Contact the workspace administrator at Open Source Firmware for an invitation.

How does one do this?

illustrations to explain Heads structure

Use something like draw.io to illustrate some of the complicated processes and structures in Heads.

  • Location of different keys
  • Ring of trust between Heads ROM, USB security dongle and TPM.
    • What happens when one of these has been tampered with.

Build breaks

Hi team,
Looks like something broke with musl-linux gcc. Says "command not found". See partial build dump below,
I am on the same system that was working earlier. Just tried a fresh git clone and make.

You can now run IASL ACPI compiler from /home/madhan/heads/build/coreboot-4.8.1/util/crossgcc/xgcc.
make[2]: Leaving directory '/home/madhan/heads/build/coreboot-4.8.1'
#echo '******* Building crossgcc-arm (this might take a while) *****'
#/home/madhan/heads/build/make-4.2.1/make -C "/home/madhan/heads/build/coreboot-4.8.1" crossgcc-arm
2019-11-06 13:14:15+05:30 CONFIG coreboot
git clone https://github.com/GregorR/musl-cross "/home/madhan/heads/build/musl-cross-git"
Cloning into '/home/madhan/heads/build/musl-cross-git'...
remote: Enumerating objects: 129, done.
remote: Counting objects: 100% (129/129), done.
remote: Compressing objects: 100% (78/78), done.
remote: Total 925 (delta 58), reused 118 (delta 50), pack-reused 796
Receiving objects: 100% (925/925), 342.27 KiB | 490.00 KiB/s, done.
Resolving deltas: 100% (557/557), done.
cd /home/madhan/heads/build/musl-cross-git && git submodule update --init --checkout
if [ -r patches/musl-cross.patch ]; then ( cd /home/madhan/heads/build/musl-cross-git ; patch -p1 ) < patches/musl-cross.patch || exit 1 ; fi
patching file config.sh
if [ -d patches/musl-cross ] && [ -r patches/musl-cross ] ; then for patch in patches/musl-cross/
.patch ; do echo "Applying patch file : $patch " ; ( cd /home/madhan/heads/build/musl-cross-git ; patch -p1 ) < $patch || exit 1 ; done ; fi
2019-11-06 13:14:25+05:30 CONFIG musl-cross
2019-11-06 13:14:25+05:30 MAKE musl-cross
2019-11-06 13:40:13+05:30 DONE musl-cross
2019-11-06 13:40:14+05:30 WGET https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.14.62.tar.xz
--2019-11-06 13:40:14-- https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.14.62.tar.xz
Resolving cdn.kernel.org (cdn.kernel.org)... 151.101.193.176, 151.101.129.176, 151.101.65.176, ...
Connecting to cdn.kernel.org (cdn.kernel.org)|151.101.193.176|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 100957512 (96M) [application/x-xz]
Saving to: '/home/madhan/heads/packages/linux-4.14.62.tar.xz.tmp'

/home/madhan/heads/ 100%[===================>] 96.28M 1.68MB/s in 77s

2019-11-06 13:41:33 (1.25 MB/s) - '/home/madhan/heads/packages/linux-4.14.62.tar.xz.tmp' saved [100957512/100957512]

echo "51ca4d7e8ee156dc0f19bc7768915cfae41dbb0b4f251e4fa8b178c5674c22ab /home/madhan/heads/packages/linux-4.14.62.tar.xz" | sha256sum --check -
/home/madhan/heads/packages/linux-4.14.62.tar.xz: OK
tar -xf "/home/madhan/heads/packages/linux-4.14.62.tar.xz" -C "/home/madhan/heads/build"
if [ -r patches/linux-4.14.62.patch ]; then ( cd /home/madhan/heads/build/linux-4.14.62 ; patch -p1 ) < patches/linux-4.14.62.patch || exit 1 ; fi
if [ -d patches/linux-4.14.62 ] && [ -r patches/linux-4.14.62 ] ; then for patch in patches/linux-4.14.62/*.patch ; do echo "Applying patch file : $patch " ; ( cd /home/madhan/heads/build/linux-4.14.62 ; patch -p1 ) < $patch || exit 1 ; done ; fi
Applying patch file : patches/linux-4.14.62/0000-efi_bds.patch
patching file arch/x86/boot/compressed/eboot.c
Applying patch file : patches/linux-4.14.62/0001-fake-acpi.patch
patching file drivers/acpi/acpica/evxfevnt.c
patching file drivers/acpi/acpica/hwacpi.c
Applying patch file : patches/linux-4.14.62/0002-nmi-squelch.patch
patching file arch/x86/kernel/nmi.c
Hunk #1 succeeded at 292 (offset -11 lines).
Hunk #2 succeeded at 302 (offset -11 lines).
Applying patch file : patches/linux-4.14.62/0003-fake-trampoline.patch
patching file arch/x86/realmode/init.c
Hunk #1 succeeded at 37 (offset 2 lines).
Hunk #2 succeeded at 151 (offset 13 lines).
Applying patch file : patches/linux-4.14.62/0010-winterfell-ahci.patch
patching file drivers/ata/libahci.c
Hunk #1 succeeded at 543 (offset 6 lines).
2019-11-06 13:42:14+05:30 CONFIG linux
2019-11-06 13:42:23+05:30 MAKE linux
tail /home/madhan/heads/build/log/linux.log

SYSHDR arch/x86/include/generated/uapi/asm/unistd_64.h
SYSHDR arch/x86/include/generated/uapi/asm/unistd_x32.h
make[4]: /home/madhan/heads/build/../crossgcc/x86_64-linux-musl/bin/x86_64-musl-linux-gcc: Command not found
HOSTCC scripts/basic/bin2c
make[4]: /home/madhan/heads/build/../crossgcc/x86_64-linux-musl/bin/x86_64-musl-linux-gcc: Command not found
HOSTCC arch/x86/tools/relocs_32.o
HOSTCC arch/x86/tools/relocs_64.o
HOSTCC arch/x86/tools/relocs_common.o
HOSTLD arch/x86/tools/relocs
make[4]: /home/madhan/heads/build/../crossgcc/x86_64-linux-musl/bin/x86_64-musl-linux-gcc: Command not found
CHK include/config/kernel.release
UPD include/config/kernel.release
make[4]: /home/madhan/heads/build/../crossgcc/x86_64-linux-musl/bin/x86_64-musl-linux-gcc: Command not found
Using .. as source for kernel
make[4]: /home/madhan/heads/build/../crossgcc/x86_64-linux-musl/bin/x86_64-musl-linux-gcc: Command not found
Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: -fstack-protector-strong not supported by compiler
make[4]: *** [/home/madhan/heads/build/linux-4.14.62/Makefile:1110: prepare-compiler-check] Error 1
make[3]: *** [Makefile:146: sub-make] Error 2
make[2]: *** [Makefile:24: __sub-make] Error 2
make[2]: Leaving directory '/home/madhan/heads/build/linux-4.14.62/linux-qemu'
make[1]: *** [Makefile:378: /home/madhan/heads/build/linux-4.14.62/linux-qemu/.build] Error 1
make[1]: Leaving directory '/home/madhan/heads'
Makefile:584: recipe for target 'all' failed
make: *** [all] Error 2

Notes on how to audit a maximized flashed firmware image

This is raw notes. This will get edited multiple times prior of having a base to create a wiki page.

The quick way, no-brainer, is to reflash the same downloaded/compiled firmware and keeping settings, as already documented at:
https://osresearch.net/Updating#reflashing-the-same-firmware

Unless flashrom itself was compromised (meaning that the payload is tampered), reflashing the same firmware image using the menu options to flash new firmware while keeping settings will reflash IFD+ME+GBE+coreboot+payload+current CBFS files. Since coreboot measures its bootblock + ramstage+romstage+payload, and then Heads measures added CBFS content, TOTP/HOTP measurements should be the same, and TOTP/HOTP unsealing of secrets should match.

But that doesn't answer the introspection need of some users to actually validate that the firmware components are actually in the expected state. And those notes, even better, if translated into code, should answer those needs.


Taking an internal backup of the firmware to be inspected externally

From Heads Recovery console, one can easily obtain actual BOARD_NAME and FW_VER that includes the bits we want to differenciate properly the actual board and flashed Heads commit ID in case we want to go back.

From Heads recovery shell, with a USB thumb drive ready to receive backup, we mount usb drive in read+write and we take a backup with proper naming scheme:

mount-usb rw
flashrom -p internal -r /media/$CONFIG_BOARD-$(echo $FW_VER|awk -F ' ' '{print $2}'_backup.rom
umount /media

Extracting content from that firmware image for validation

Unfortunately, coreboot-utils are precompiled for a limited number of distributions today. I'll take for granted here that debian12 is installed under QubesOS (see unman's repo https://qubes.3isec.org/Templates_4.1/)
Then a quick sudo apt install coreboot-utils binwalk will make the tools available with/without sudo.

Each Heads board's build comes with a hashes.txt file. It is either dowloadable from CircleCI artifacts, or can be seen, and copy pasted from a build's output given on screen.
Following download instructions will lead you to the hashes step of any CircleCI build: https://osresearch.net/Downloading

Now.
After having mounted our USB thumb drive under a debian-12 based qube with tools installed, from command line, having passed the USB thumb drive to our newly booted qube:

sudo mount /dev/sda1 /media
mkdir -p /tmp/inspection
cp /media/x230-hotp-maximized-Heads-v0.2.0-1296-g139ecb8_backup.rom /tmp/inspection
cd /tmp/inspection

And then we work on our copied to memory image.

We can extract partitions not managed from coreboot actual versions measurements:

user@heads-backup-extraction:/tmp/inspection$ ifdtool -x x230-hotp-maximized-Heads-v0.2.0-1296-g139ecb8_backup.rom
File x230-hotp-maximized-Heads-v0.2.0-1296-g139ecb8_backup.rom is 12582912 bytes
  Flash Region 0 (Flash Descriptor): 00000000 - 00000fff 
  Flash Region 1 (BIOS): 0001b000 - 00bfffff 
  Flash Region 2 (Intel ME): 00003000 - 0001afff 
  Flash Region 3 (GbE): 00001000 - 00002fff 
  Flash Region 4 (Platform Data): 00fff000 - 00000fff (unused)
user@heads-backup-extraction:/tmp/inspection$ ls -al
total 24592
drwxr-xr-x  3 user user     4096 Nov 25 10:56 .
drwxrwxrwt 12 root root     4096 Nov 25 11:22 ..
-rw-r--r--  1 user user     4096 Nov 25 12:05 flashregion_0_flashdescriptor.bin
-rw-r--r--  1 user user 12472320 Nov 25 12:05 flashregion_1_bios.bin
-rw-r--r--  1 user user    98304 Nov 25 12:05 flashregion_2_intel_me.bin
-rw-r--r--  1 user user     8192 Nov 25 12:05 flashregion_3_gbe.bin
-rw-r--r--  1 user user 12582912 Nov 25 10:14 x230-hotp-maximized-Heads-v0.2.0-1296-g139ecb8_backup.rom

Here one could compare ME against what is downloaded and extracted from Heads scripts, GBE and IFD configs against what is stored under Heads tree.

But most questions are related to the firmware integrity itself, Heads itself:

user@heads-backup-extraction:/tmp/inspection$  cbfstool x230-hotp-maximized-Heads-v0.2.0-1296-g139ecb8_backup.rom print
FMAP REGION: COREBOOT
Name                           Offset     Type           Size   Comp
cbfs master header             0x0        cbfs header        32 none
fallback/romstage              0x80       (unknown)       85100 none
cpu_microcode_blob.bin         0x14d80    microcode       26624 none
fallback/ramstage              0x1b600    (unknown)       97676 none
config                         0x33400    raw               834 none
revision                       0x33780    raw               691 none
fallback/dsdt.aml              0x33a80    raw             14615 none
vbt.bin                        0x37400    raw              1433 LZMA (4281 decompressed)
cmos_layout.bin                0x37a00    cmos_layout      1884 none
fallback/postcar               0x381c0    (unknown)       25816 none
fallback/payload               0x3e700    simple elf    7320519 none
heads/initrd/.gnupg/pubring.kbx 0x739b00   raw             11549 none
heads/initrd/.gnupg/trustdb.gpg 0x73c880   raw              1320 none
heads/initrd/etc/config.user   0x73ce00   raw                22 none
(empty)                        0x73ce80   null          4337432 none
bootblock                      0xb5fdc0   bootblock       65536 none

Here again, a lot of stuff there.

Get build hashes for current rom

x230-hotp-maximized-Heads-v0.2.0-1296-g139ecb8_backup.rom is commit 139ecb8
We go over linuxboot/heads@139ecb8
We click grewn mark, follow the rabbit to the build for x230-hot-maximized at https://app.circleci.com/jobs/github/osresearch/heads/5448, click the "Output hashes" if this is an old build without artifacts, and copy the output of the hashes there to a local hashes.txt file we make sure to have available for our situation. We can directly save the output from CircleCI's Download Icon, which in our case leads to https://circleci.com/api/v1.1/project/github/osresearch/heads/5448/output/104/0?file=true&allocation-id=63751e76e6fb893f12bf3473-0-build%2F97AF006

From now on I consider we have that file saved into hashes.txt to be used locally.

Extract content from coreboot's payload

user@heads-backup-extraction:/tmp/inspection$ mkdir -p payload_content
user@heads-backup-extraction:/tmp/inspection$ cbfstool x230-hotp-maximized-Heads-v0.2.0-1296-g139ecb8_backup.rom extract -n fallback/payload -f payload_content/payload -m x86

We now have coreboot's payload.

user@heads-backup-extraction:/tmp/inspection/payload_content$ ls -al
total 7180
drwxr-xr-x 2 user user    4096 Nov 25 12:22 .
drwxr-xr-x 3 user user    4096 Nov 25 10:56 ..
-rw-r--r-- 1 user user   11525 Nov 25 10:58 hashes.txt
-rw-r--r-- 1 user user 7328543 Nov 25 12:14 payload

We extract the content with binwalk

user@heads-backup-extraction:/tmp/inspection/payload_content$ binwalk --extract payload 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ELF, 32-bit LSB executable, Intel 80386, version 1 (SYSV)
13013         0x32D5          xz compressed data
2072933       0x1FA165        MySQL MISAM compressed data file Version 8
2910340       0x2C6884        bix header, header size: 64 bytes, header CRC: 0xE802F8, created: 2106-02-07 01:21:09, image size: 186 bytes, Data Address: 0x1000000, Entry Point: 0x83BB9000, data CRC: 0x50F, compression type: none, image name: ""
2923392       0x2C9B80        xz compressed data
3035935       0x2E531F        xz compressed data

user@heads-backup-extraction:/tmp/inspection/payload_content$ ls -al
total 7184
drwxr-xr-x 3 user user    4096 Nov 25 12:22 .
drwxr-xr-x 3 user user    4096 Nov 25 10:56 ..
-rw-r--r-- 1 user user   11525 Nov 25 10:58 hashes.txt
-rw-r--r-- 1 user user 7328543 Nov 25 12:14 payload
drwxr-xr-x 2 user user    4096 Nov 25 12:22 _payload.extracted

user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ ls | while read file; do sha256sum $file; done | while read line; do hash=$(echo $line | awk -F " " '{print $1}'); file=$(echo $line | awk -F " " '{print $2}'); grep $hash ../hashes.txt && echo "we have match for $hash in $file"; done
b3387d6b04c6246198638a46a2fec5bb7623a99a97189a26c5e019524aef8992  build/x86/x230-hotp-maximized/initrd.cpio.xz
we have match for b3387d6b04c6246198638a46a2fec5bb7623a99a97189a26c5e019524aef8992 in 2E531F.xz

So we have a matching initrd.cpio.xz into 2E531F.xz
We could dig more into that, and will (after all, everything hashes.txt is detailing why we have a match for the payload).

hashes.txt can be used under recovery shell to verify hashes of the initrd binaries

The paths undr hashes.txt are relative. If we have hashes.txt under USB thumb drive, from Heads recovery shell:
cd /
mount-usb
sha256sum -c /media/hashes.txt

Will give OK reports for all files that were found, including libraries and binaries and scripts user by heads, as seen under

Check bzImage

Unfortunately, this requires CircleCI bzImage since mathing can only be made against decompressed binary.

After our binwalk --extract command:

user@heads-backup-extraction:/tmp/inspection/payload_content$ cd _payload.extracted/
user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ ls
2C9B80.xz  2E531F  2E531F.xz  32D5  32D5.xz
user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ wget -O extract-vmlinux https://raw.githubusercontent.com/torvalds/linux/master/scripts/extract-vmlinux
user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ chmod +x ./extract-vmlinux 
user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ ls -al
total 47316
drwxr-xr-x 2 user user     4096 Nov 25 12:34 .
drwxr-xr-x 3 user user     4096 Nov 25 12:22 ..
-rw-r--r-- 1 user user  4405151 Nov 25 12:22 2C9B80.xz
-rw-r--r-- 1 user user 12882944 Nov 25 12:22 2E531F
-rw-r--r-- 1 user user  4292608 Nov 25 12:22 2E531F.xz
-rw-r--r-- 1 user user 19528104 Nov 25 12:22 32D5
-rw-r--r-- 1 user user  7315530 Nov 25 12:22 32D5.xz
-rwxr-xr-x 1 user user     1695 Nov 25 12:34 extract-vmlinux

user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ ./extract-vmlinux 32D5 > vmlinux_local

Download bzImage from CircleCI artifact

user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ ./extract-vmlinux bzImage > vmlinux_remote
user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$ diff vmlinux_local vmlinux_remote
user@heads-backup-extraction:/tmp/inspection/payload_content/_payload.extracted$

Better explain Heads functionnings and limitation

Edit: best unbiased, user written doc at https://tech.michaelaltfield.net/2023/02/16/evil-maid-heads-pureboot/


The following should go into a wiki page.

Actual Heads security mechanisms are:

  1. Measured /boot, requiring a USB Security dongle to offload GPG operations (signing with private key in smartcard). The verification of detached signed /boot digest is automatic on each boot, verified against public key injected in firmware (and measured by TPM).

  2. Firmware remote attestation (TOTP, HOTP) of measured firmware components, including GPG public key into PCR7, used to provide validation of detached signed digest of precedent step.

  3. Disk Unlock Key, using NV TPM reserved space to release Disk Unlock Key when (1) (2) and LUKS header + Disk Unlock Key passphrase are valid, while rate limiting passphrase attempts by the TPM. (Note that if going into recovery shell, measurements are invalidated and this won't be successful)

Let's focus on (1) here.

  1. On each boot, Heads verifies that the detached signed digest (/boot/kexec.sig) matches the digest(/boot/kexec_hashes.txt). (Verified authenticity and integrity with public key matching private key in USB Security dongle's smartcard).
  2. Heads generates a new sha256sum digest of /boot found files (sha256sum of /boot files) and compares its result against signed one (/boot/kexec_hashes.txt)
  3. If there is a mismatch of integrity of past signed digest, the difference of integrity are showed. If there are new files not in digest, those are shown as errors. Both are different. For example, grub.cfg having changed (grub.cfg) and a new file (xen or kernel) gives hints of what changed in case the user forgot to reboot his computer directly after a core upgrade to sign related changes and keep his workflow worry free.
  • The public key needs to be injected in rom to have detached signature validation under Heads.
  • The private key should not be exposed to the operating system. Having access to a copy of private key and knowing its PIN would permit all content having been crypted to be decrypted (no forward secrecy with GPG). Having access to that private key would also permit an attacker to sign changes as if he was the user.
  • A USB Security dongle normally implements rate limiting on password prompts. More radically, USB Security dongles are actually locking the user out of their User role if 3 bad attempts were made, actually protecting the private key of abuse. In such case, the Admin role of the USB Security dongle is required to unlock the User role so the key can be used again. Having a private key exposed offers unlimited attempts.

For more information, please read: https://www.linuxjournal.com/content/why-smart-cards-are-smart

Update Heads repo with librem script for x230 and debian install

Hi all,

Purism did a great job to simplify heads build and install. Is it possible for the project to update doc and script with librem's one?
The current doc is hard to understand (where to start, how to properly install debian based system, how to flash with existing coreboot rom...)

Let me know if I can help in any way :-)

Distrust the Infrastructure

hi @tlaurion

do Heads & Core-boot distrust the infrastructure,
by signing all commit, before being pushed to Github ?

also during build by Circle CI,
does it verify each file first before build ?

thanks and regards,

Can I use a single USB Security (GPG) dongle with multiple computers?

Asked on slack/matrix channel:

If I get a USB dongle, can I use the same one for multiple laptops installed with heads?


Answer:

You can use one USB Security dongle for multiple computers if you choose non-hotp variants of board configurations (the x230-maximized board config option in your use case; not x230-hotp-maximized) for multiple platforms you own.

Doing so will permit usage of a single USB Security dongle across multiple computers to detach sign content /boot content from a single USB Security dongle, and verified at each boot against the public key that was injected in each of your computers ROMS. This means that one laptop will do the Factory Reset/Re-Ownership wizard, and you will have that resulting public key backuped on a USB thumb drive. On other laptops, you will inject that generated public key in all other non-hotp flashed hardware.

Firmware remote attestation will happen through TOTP (Qr code generation on laptop, scanning from smartphone TOTP supporting app) after injecting the key, sealing firmware measurements (including your keyring and trustdb measurements), where you will give distinctive names to each laptops in the 2fa app at the time of scanning Qr code on your smartphone.

As a side effect of this, TOTP makes you rely on time synchronization to always be in sync (UTC timezone) between your laptops and phone to produce a TOTP unique number every 30 seconds that would match the ones presented on your smartphone at boot. This means that laptops staying offline for longer periods of time will have to have their time either automatically synced through Ethernet (network-init-recovery script called from command line) or manually through the recovery shell (date -s "HH:MM:SS" followed by hwclock -w commands to set time and write it to system clock).

HOTP enabled board configuration variants actively bounds a single laptop to a single HOTP supporting usb dongle for remote attestation. This means that you could use Nitrokey Pro/Nitrokey Storage/Librem Key on your main computer using it with x230-hotp-maximized board variant so that visual firmware integrity validation is enabled on that main laptop, while using other laptops you own with non-hotp variant flashed on them. Unfortunately, there is only one HOTP slot on Librem Key/Nitrokey Pro/Nitrokey Storage that can be used for integrity attestation, and is a limitation from Nitrokey firmware, which can be discussed on Nitrokey firmware github to be fixed accordingly (and then managed properly inside of Heads).

Should we document this better in the heads-wiki/osresearch.net? Can you provide a pull request where things were not clear enough for you to understand the above?

trmm.net required changes

@osresearch Noticed the following broken links reviewing content

https://trmm.net/Heads_threat_model
This section needs to be expanded to describe different threat models for different users. As @corcra says, "your threat model is not my threat model but your threat model is ok". The EFF has written the Surveillance Self-Defense guide that has a good introduction to generating threat models. The Center for Investigative Journalism has a good four part article on threats/defences, basic physical modifications, advanced modifications and replacing the BIOS.

www.tcij.org is now login based :(

Replacement links:

bad links without archives:

Provisioning Yubikey 5 Nano for Heads configuration

To implement: Needs forcesig check and toggle if disabled so factory reset works in all cases: #102 (comment)


hi @tlaurion

i see the Heads wiki has been improved a lot than before, and it is great.

do you mind to add steps about how to provision a new Yubikey and export its public key ?
or maybe there is any good references about that ?

do we have to choose between using the original private key in the Yubikey,
or generate key, then store it inside Yubikey ?

dead links in wiki

All internal links at least at the index.md are pointing to nowhere (404).

Confusion about using USB Security Dongles to decrypt hard drive

As far as I understand, you can use your - for example Nitrokey Pro - to "avoid" typing in the Disk Recovery Key. The Disk Recovery Key is the key used at OS installation for the encrypted root partition (passphrase placed in LUKS keyslot 0). So I can use this key whenever I connect my harddrive to another computer.

For me, it would be logical, if I use my GPG key on my Nitrokey to do some magic to decrypt my harddrive (or decrypt some parts on the TPM which then decrypts my harddrive). It would make sense, if I would need to type in my Nitrokey User PIN to decrypt my harddrive.

Instead I am asked for another password in Heads when I try to set up this. This confuses me.

I read https://osresearch.net/Keys/

(Added for newcomers: The Nitrokey User PIN is - obviously - relatively easy to guess, if brute force methods are available. But the USB Security dongles are actually locking the user out of their User role if 3 bad attempts were made, so it is safe, to use the PIN to unlock/decrypt my harddrive.)

RTC clock drifting problems - manual/automatic correction guides

Not sure how that happeneds and from where (or if Mandala effect... Was that ever documented?!) , but I have found no reference under osresearch.net on ntp/skew/time/date to automatically set/manually correct time after first flash and/or in case of a bad RTC battery.

Bad RTC battery is a pretty common thing across second hand bought devices, but not as much impactful as under Heads, where valid time is needed to generate keys, sign and validate signed content and generate TOTP code which will be invalid if time skew can be of 20 years, unless synced from OS over network first thing when connected, sometimes going unnoticed per users but while still being problematic anyhow from a log perspective, if that only that matters.

There is currently no actual reference to network-recovery-init to sync time against router through NTP protocol.
Nor manual instructions on fixing the time in case of linuxboot/heads#1021 (which is most probably a bad RTC clock battery, needing to be changed, but how users can know if not documented).

Menu options will permit to go to console, and give instructions in case of invalid TOTP code, but as linuxboot/heads#1021 shows us, there are real problems into not documenting this properly, since users may not reach Heads and therefore Heads menus to get to the console with proper instructions from that Heads menu option.

Basically, an Heads entree should be added under heads-wiki so that users can easily find what is documented under linuxboot/heads#1021 (comment). Referenced through FAQ?

@githubuseravailable: where would you have loved to see that documented?

qemu-coreboot scsi not working as expected

Hi,
I am new to the Heads project and trying to get things working on qemu before jumping to the actual hardware ( I have the x630 in mind ).
I was able to build with "make BOARD=qemu-coreboot" and got the file "build/qemu-coreboot/coreboot.rom".
Then I try to run it in qemu with command line parameters as follows:
sudo qemu-system-x86_64 -machine q35,smm=on -global ICH9-LPC.disable_s3=1 -global driver=cfi.pflash01,property=secure,value=on -drive if=pflash,format=raw,unit=0,file=./linuxboot.rom --serial /dev/tty -device virtio-scsi-pci,id=scsi-hd -drive if=none,file=cirros-0.4.0-x86_64-disk.img,id=disk,format=qcow2,boot=on,cache=writeback -device scsi-hd,drive=disk

The coreboot loads and gets to the boot menu. At this point I select option "y-default boot"
It says "mounting /dev/sda1 on /boot failed: No such file or directory".

I am expecting the cirrusOS image to be mounted as a scsi drive inside coreboot and OS to boot from that. Is this a valid expectation?

I see lspci list the device.
I do not see lsscsi list anything.
There is no sda entries under /dev
I do not see any scsi name drivers under /lib/modules

Am I trying to do something not supported? How do I go forward? Any pointers to documents, links, or if anyone has faced and solved this please help.

Thanks in advance.

Add gui-init related screenshots and explanations

Should we take parts from Purism documentation and videos?

Heads-wiki documentation is still linked to deprecated generic-init usage which is not useful to most boards anymore and replaced with gui-init usage, being fbwhiptail based or whiptail based, working also over serial connections for servers and user friendly, using the same gui-init to render over framebuffer or simple tty, which was more tested and user friendlier then generic-init.

Linked to linuxboot/heads#477 (I think we can close, actually.)

Help wanted.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.