diff options
Diffstat (limited to 'gnu/build/chromium-extension.scm')
-rw-r--r-- | gnu/build/chromium-extension.scm | 169 |
1 files changed, 72 insertions, 97 deletions
diff --git a/gnu/build/chromium-extension.scm b/gnu/build/chromium-extension.scm index d65df09f37..656034b80f 100644 --- a/gnu/build/chromium-extension.scm +++ b/gnu/build/chromium-extension.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2020 Marius Bakke <marius@gnu.org> +;;; Copyright © 2020, 2021 Marius Bakke <marius@gnu.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -17,13 +17,8 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu build chromium-extension) - #:use-module (gcrypt base16) - #:use-module ((gcrypt hash) #:prefix hash:) - #:use-module (ice-9 iconv) #:use-module (guix gexp) #:use-module (guix packages) - #:use-module (gnu packages base) - #:use-module (gnu packages check) #:use-module (gnu packages chromium) #:use-module (gnu packages gnupg) #:use-module (gnu packages tls) @@ -39,28 +34,30 @@ (define (make-signing-key seed) "Return a derivation for a deterministic PKCS #8 private key using SEED." + (computed-file + (string-append seed "-signing-key.pem") + (with-extensions (list guile-gcrypt) + #~(begin + (use-modules (gcrypt base16) (gcrypt hash) (ice-9 iconv)) + (let* ((sha256sum (bytevector->base16-string + (sha256 (string->bytevector #$seed "UTF-8")))) + ;; certtool.c wants a 56 byte seed for a 2048 bit key. + (key-size 2048) + (normalized-seed (string-take sha256sum 56))) - (define sha256sum - (bytevector->base16-string (hash:sha256 (string->bytevector seed "UTF-8")))) - - ;; certtool.c wants a 56 byte seed for a 2048 bit key. - (define size 2048) - (define normalized-seed (string-take sha256sum 56)) - - (computed-file (string-append seed "-signing-key.pem") - #~(system* #$(file-append gnutls "/bin/certtool") - "--generate-privkey" - "--key-type=rsa" - "--pkcs8" - ;; Use the provable FIPS-PUB186-4 algorithm for - ;; deterministic results. - "--provable" - "--password=" - "--no-text" - (string-append "--bits=" #$(number->string size)) - (string-append "--seed=" #$normalized-seed) - "--outfile" #$output) - #:local-build? #t)) + (system* #$(file-append gnutls "/bin/certtool") + "--generate-privkey" + "--key-type=rsa" + "--pkcs8" + ;; Use the provable FIPS-PUB186-4 algorithm for + ;; deterministic results. + "--provable" + "--password=" + "--no-text" + (string-append "--bits=" (number->string key-size)) + (string-append "--seed=" normalized-seed) + "--outfile" #$output)))) + #:local-build? #t)) (define* (make-crx signing-key package #:optional (package-output "out")) "Create a signed \".crx\" file from the unpacked Chromium extension residing @@ -68,9 +65,9 @@ in PACKAGE-OUTPUT of PACKAGE. The extension will be signed with SIGNING-KEY." (define name (package-name package)) (define version (package-version package)) - (with-imported-modules '((guix build utils)) - (computed-file - (string-append name "-" version ".crx") + (computed-file + (string-append name "-" version ".crx") + (with-imported-modules '((guix build utils)) #~(begin ;; This is not great. We pull Xorg and Chromium just to Zip and ;; sign an extension. This should be implemented with something @@ -78,27 +75,24 @@ in PACKAGE-OUTPUT of PACKAGE. The extension will be signed with SIGNING-KEY." (use-modules (guix build utils)) (let ((chromium #$(file-append ungoogled-chromium "/bin/chromium")) (xvfb #$(file-append xorg-server "/bin/Xvfb")) - (packdir "/tmp/extension")) - (mkdir-p (dirname packdir)) - (copy-recursively (ungexp package package-output) packdir) + (packdir (string-append (getcwd) "/extension"))) + (mkdir packdir) + (copy-recursively (ungexp package package-output) packdir + ;; Ensure consistent file modification times. + #:keep-mtime? #t) (system (string-append xvfb " :1 &")) (setenv "DISPLAY" ":1") (sleep 2) ;give Xorg some time to initialize... ;; Chromium stores the current time in the .crx Zip archive. ;; Use a fixed timestamp for deterministic behavior. - ;; FIXME (core-updates): faketime is missing an absolute reference - ;; to 'date', hence the need to set PATH. - (setenv "PATH" #$(file-append coreutils "/bin")) - (invoke #$(file-append libfaketime "/bin/faketime") - "2000-01-01 00:00:00" - chromium + (invoke chromium "--user-data-dir=/tmp/signing-profile" (string-append "--pack-extension=" packdir) (string-append "--pack-extension-key=" #$signing-key)) - (copy-file (string-append packdir ".crx") #$output))) - #:local-build? #t))) + (copy-file (string-append packdir ".crx") #$output)))) + #:local-build? #t)) -(define* (crx->chromium-json crx version) +(define (crx->chromium-json crx version) "Return a derivation that creates a Chromium JSON settings file for the extension given as CRX. VERSION is used to signify the CRX version, and must match the version listed in the extension manifest.json." @@ -127,66 +121,47 @@ format." "--outder") #:local-build? #t)) -(define (chromium-json->profile-object json signing-key) - "Return a derivation that installs JSON to the directory searched by -Chromium, using a file name (aka extension ID) derived from SIGNING-KEY." - (define der (signing-key->public-der signing-key)) - +(define (file-sha256sum file) (with-extensions (list guile-gcrypt) - (with-imported-modules '((guix build utils)) - (computed-file - "chromium-extension" - #~(begin - (use-modules (guix build utils) - (gcrypt base16) - (gcrypt hash)) - (define (base16-string->chromium-base16 str) - ;; Translate STR, a hexadecimal string, to a Chromium-style - ;; representation using the letters a-p (where a=0, p=15). - (define s1 "0123456789abcdef") - (define s2 "abcdefghijklmnop") - (let loop ((chars (string->list str)) - (converted '())) - (if (null? chars) - (list->string (reverse converted)) - (loop (cdr chars) - (cons (string-ref s2 (string-index s1 (car chars))) - converted))))) - - (let* ((checksum (bytevector->base16-string (file-sha256 #$der))) - (file-name (base16-string->chromium-base16 - (string-take checksum 32))) - (extension-directory (string-append #$output - "/share/chromium/extensions"))) - (mkdir-p extension-directory) - (symlink #$json (string-append extension-directory "/" - file-name ".json")))) - #:local-build? #t)))) + #~(begin + (use-modules (gcrypt base16) (gcrypt hash)) + (bytevector->base16-string (file-sha256 #$file))))) -(define* (make-chromium-extension p #:optional (output "out")) - "Create a Chromium extension from package P and return a package that, -when installed, will make the extension contained in P available as a -Chromium browser extension. OUTPUT specifies which output of P to use." - (let* ((pname (package-name p)) - (version (package-version p)) - (signing-key (make-signing-key pname))) +(define* (make-chromium-extension pkg #:optional (pkg-output "out")) + "Create a Chromium extension from package PKG and return a package that, +when installed, will make the extension contained in PKG available as a +Chromium browser extension. PKG-OUTPUT specifies which output of PKG to use." + (let* ((name (package-name pkg)) + (version (package-version pkg)) + (private-key (make-signing-key name)) + (public-key (signing-key->public-der private-key)) + (checksum (file-sha256sum public-key)) + (crx (make-crx private-key pkg pkg-output)) + (json (crx->chromium-json crx version))) (package - (inherit p) - (name (string-append pname "-chromium")) + (inherit pkg) + (name (string-append name "-chromium")) (source #f) - (build-system trivial-build-system) (native-inputs '()) - (inputs - `(("extension" ,(chromium-json->profile-object - (crx->chromium-json (make-crx signing-key p output) - version) - signing-key)))) + (inputs '()) (propagated-inputs '()) (outputs '("out")) + (build-system trivial-build-system) (arguments - '(#:modules ((guix build utils)) - #:builder - (begin - (use-modules (guix build utils)) - (copy-recursively (assoc-ref %build-inputs "extension") - (assoc-ref %outputs "out")))))))) + (list #:modules '((guix build utils)) + #:builder + #~(begin + (use-modules (guix build utils)) + (define (base16-char->chromium-base16 char) + ;; Translate CHAR, a hexadecimal character, to a Chromium-style + ;; representation using the letters a-p (where a=0, p=15). + (string-ref "abcdefghijklmnop" + (string-index "0123456789abcdef" char))) + (let ((file-name (string-map base16-char->chromium-base16 + (string-take #$checksum 32))) + (extension-directory + (string-append #$output + "/share/chromium/extensions"))) + (mkdir-p extension-directory) + (symlink #$json (string-append extension-directory "/" + file-name ".json"))))))))) |