1#!/bin/bash 2# Copyright 2024 The ChromiumOS Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5# 6# Generates PEM encoded private key from a .vbprivk 7 8# Load common constants and functions. 9# shellcheck source=common.sh 10# shellcheck disable=SC1091 11. "$(dirname "$0")/common.sh" 12 13set -eu -o pipefail 14 15usage() { 16 cat <<EOF 17Usage: $0 [options] 18 19Options: 20 --input <file> vbprivk private key (default: stdin) 21 --output <file> PEM encoded private key (default: stdout) 22EOF 23 24 if [[ $# -ne 0 ]]; then 25 die "unknown option $*" 26 else 27 exit 0 28 fi 29} 30 31# Reads a signed 64 bit integer from stdin 32readi64() { 33 local output 34 output="$(od --address-radix=none --read-bytes=8 --format=d8)" 35 # Drop leading padding and zeros 36 echo "$(("${output}"))" 37} 38 39main() { 40 local input_fd=0 # stdin 41 local output_fd=1 # stdout 42 while [[ $# -gt 0 ]]; do 43 case $1 in 44 --input) 45 if ! exec 3< "$2"; then 46 die "Failed to open input file '$2'" 47 fi 48 input_fd=3 49 shift 50 ;; 51 --output) 52 if ! exec 4> "$2"; then 53 die "Failed to open output file '$2'" 54 fi 55 output_fd=4 56 shift 57 ;; 58 -h|--help) 59 usage 60 ;; 61 *) 62 usage "$1" 63 ;; 64 esac 65 shift 66 done 67 68 # A `vbprivk` is comprised of an 8 byte header followed by a DER encoded 69 # PKCS#1 RSA Private Key. We read the 8 byte header from the input_fd 70 # (which increments file position) and verify that it's a sane value. 71 # 72 # See /vboot_reference/firmware/2lib/include/2crypto.h 73 local vb2_crypto_algorithm 74 vb2_crypto_algorithm="$(readi64 <&"${input_fd}")" 75 76 if [[ "${vb2_crypto_algorithm}" -lt 0 || \ 77 "${vb2_crypto_algorithm}" -gt 17 ]]; then 78 die "Unknown vbprivk format" 79 fi 80 81 # Convert the remainder of the input_fd to base64. 82 echo -n "-----BEGIN RSA PRIVATE KEY----- 83$(base64 --wrap=64 <&"${input_fd}") 84-----END RSA PRIVATE KEY----- 85" >&"${output_fd}" 86} 87main "$@" 88