Merge pull request #14 from jmichelp/master
Change the way private key and cert are embedded.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,5 +3,3 @@ Cargo.lock
|
|||||||
|
|
||||||
# Prevent people from commiting sensitive files.
|
# Prevent people from commiting sensitive files.
|
||||||
crypto_data/
|
crypto_data/
|
||||||
src/ctap/key_material.rs
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ rust:
|
|||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
|
|
||||||
dist: "trusty" # we need python3-pip
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
- "python3"
|
- "python3"
|
||||||
- "python3-pip"
|
- "python3-pip"
|
||||||
|
- "python3-setuptools"
|
||||||
|
- "python3-wheel"
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
- rust
|
- rust
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ panic_console = ["libtock/panic_console"]
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
elf2tab = "0.4.0"
|
elf2tab = "0.4.0"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
openssl = "0.10"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
lto = true # Link Time Optimization usually reduces size of binaries and static libraries
|
lto = true # Link Time Optimization usually reduces size of binaries and static libraries
|
||||||
|
|||||||
78
build.rs
Normal file
78
build.rs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2019 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
extern crate openssl;
|
||||||
|
|
||||||
|
use openssl::asn1;
|
||||||
|
use openssl::ec;
|
||||||
|
use openssl::nid::Nid;
|
||||||
|
use openssl::pkey::PKey;
|
||||||
|
use openssl::x509;
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=crypto_data/opensk.key");
|
||||||
|
println!("cargo:rerun-if-changed=crypto_data/opensk_cert.pem");
|
||||||
|
|
||||||
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
|
let priv_key_bin_path = Path::new(&out_dir).join("opensk_pkey.bin");
|
||||||
|
let cert_bin_path = Path::new(&out_dir).join("opensk_cert.bin");
|
||||||
|
let aaguid_bin_path = Path::new(&out_dir).join("opensk_aaguid.bin");
|
||||||
|
|
||||||
|
// Load the OpenSSL PEM ECC key
|
||||||
|
let ecc_data = include_bytes!("crypto_data/opensk.key");
|
||||||
|
let pkey = ec::EcKey::private_key_from_pem(ecc_data)
|
||||||
|
.ok()
|
||||||
|
.expect("Failed to load OpenSK private key file");
|
||||||
|
|
||||||
|
// Check key validity
|
||||||
|
pkey.check_key().unwrap();
|
||||||
|
assert_eq!(pkey.group().curve_name(), Some(Nid::X9_62_PRIME256V1));
|
||||||
|
|
||||||
|
let mut priv_key = pkey.private_key().to_vec();
|
||||||
|
if priv_key.len() == 33 && priv_key[0] == 0 {
|
||||||
|
priv_key.remove(0);
|
||||||
|
}
|
||||||
|
assert_eq!(priv_key.len(), 32);
|
||||||
|
|
||||||
|
// Create the raw private key out of the OpenSSL data
|
||||||
|
let mut priv_key_bin_file = File::create(&priv_key_bin_path).unwrap();
|
||||||
|
priv_key_bin_file.write_all(&priv_key).unwrap();
|
||||||
|
|
||||||
|
// Convert the PEM certificate to DER and extract the serial for AAGUID
|
||||||
|
let input_pem_cert = include_bytes!("crypto_data/opensk_cert.pem");
|
||||||
|
let cert = x509::X509::from_pem(input_pem_cert)
|
||||||
|
.ok()
|
||||||
|
.expect("Failed to load OpenSK certificate");
|
||||||
|
|
||||||
|
// Do some sanity check on the certificate
|
||||||
|
assert!(cert
|
||||||
|
.public_key()
|
||||||
|
.unwrap()
|
||||||
|
.public_eq(&PKey::from_ec_key(pkey).unwrap()));
|
||||||
|
let now = asn1::Asn1Time::days_from_now(0).unwrap();
|
||||||
|
assert!(cert.not_after() > now);
|
||||||
|
assert!(cert.not_before() <= now);
|
||||||
|
|
||||||
|
let mut cert_bin_file = File::create(&cert_bin_path).unwrap();
|
||||||
|
cert_bin_file.write_all(&cert.to_der().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let mut aaguid_bin_file = File::create(&aaguid_bin_path).unwrap();
|
||||||
|
let mut serial = cert.serial_number().to_bn().unwrap().to_vec();
|
||||||
|
serial.resize(16, 0);
|
||||||
|
aaguid_bin_file.write_all(&serial).unwrap();
|
||||||
|
}
|
||||||
21
src/ctap/key_material.rs
Normal file
21
src/ctap/key_material.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2019 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
pub const AAGUID: [u8; 16] = *include_bytes!(concat!(env!("OUT_DIR"), "/opensk_aaguid.bin"));
|
||||||
|
|
||||||
|
pub const ATTESTATION_CERTIFICATE: &[u8] =
|
||||||
|
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_cert.bin"));
|
||||||
|
|
||||||
|
pub const ATTESTATION_PRIVATE_KEY: [u8; 32] =
|
||||||
|
*include_bytes!(concat!(env!("OUT_DIR"), "/opensk_pkey.bin"));
|
||||||
@@ -36,6 +36,7 @@ generate_crypto_materials () {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
force_generate="$1"
|
||||||
mkdir -p crypto_data
|
mkdir -p crypto_data
|
||||||
if [ ! -f "${ca_priv_key}" ]
|
if [ ! -f "${ca_priv_key}" ]
|
||||||
then
|
then
|
||||||
@@ -60,12 +61,12 @@ generate_crypto_materials () {
|
|||||||
-sha256
|
-sha256
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "${opensk_key}" ]
|
if [ "${force_generate}" = "Y" -o ! -f "${opensk_key}" ]
|
||||||
then
|
then
|
||||||
"${openssl}" ecparam -genkey -name prime256v1 -out "${opensk_key}"
|
"${openssl}" ecparam -genkey -name prime256v1 -out "${opensk_key}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "${opensk_cert_name}.pem" ]
|
if [ "${force_generate}" = "Y" -o ! -f "${opensk_cert_name}.pem" ]
|
||||||
then
|
then
|
||||||
"${openssl}" req \
|
"${openssl}" req \
|
||||||
-new \
|
-new \
|
||||||
@@ -83,87 +84,4 @@ generate_crypto_materials () {
|
|||||||
-out "${opensk_cert_name}.pem" \
|
-out "${opensk_cert_name}.pem" \
|
||||||
-sha256
|
-sha256
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local cert_mtime=$(stat --printf="%Y" "${opensk_cert_name}.pem")
|
|
||||||
local rust_file_mtime=0
|
|
||||||
# Only take into consideration the mtime of the file if it exists and if we're not forcing
|
|
||||||
# the rust file to be re-generated.
|
|
||||||
if [ -f "${rust_file}" -a "x$1" != "xY" ]
|
|
||||||
then
|
|
||||||
rust_file_mtime=$(stat --printf="%Y" "${rust_file}")
|
|
||||||
fi
|
|
||||||
if [ $cert_mtime -gt $rust_file_mtime ]
|
|
||||||
then
|
|
||||||
local cert_size=$("${openssl}" x509 \
|
|
||||||
-in "${opensk_cert_name}.pem" \
|
|
||||||
-outform der 2>/dev/null \
|
|
||||||
| wc -c)
|
|
||||||
local cert_serial_hex=$("${openssl}" x509 \
|
|
||||||
-in "${opensk_cert_name}.pem" \
|
|
||||||
-noout \
|
|
||||||
-serial \
|
|
||||||
| cut -d'=' -f2)
|
|
||||||
# Pad with zeroes in case the serial is too short. We don't care if the
|
|
||||||
# serial is longer than 32 characters as we will only process the first 32
|
|
||||||
# characters in the loop later.
|
|
||||||
cert_serial_hex="${cert_serial_hex}00000000000000000000000000000000"
|
|
||||||
|
|
||||||
# Create header
|
|
||||||
echo "// This file had been generated by OpenSK deploy.sh script" > "${rust_file}"
|
|
||||||
echo "" >> "${rust_file}"
|
|
||||||
|
|
||||||
echo "pub const AAGUID: [u8; 16] = [" >> "${rust_file}"
|
|
||||||
for i in `seq 0 2 30`
|
|
||||||
do
|
|
||||||
echo -n "0x${cert_serial_hex:$i:2}, " >> "${rust_file}"
|
|
||||||
done
|
|
||||||
echo "" >> "${rust_file}"
|
|
||||||
echo "];" >> "${rust_file}"
|
|
||||||
echo "" >> "${rust_file}"
|
|
||||||
|
|
||||||
echo "pub const ATTESTATION_CERTIFICATE: [u8; ${cert_size}] = [" >> "${rust_file}"
|
|
||||||
"${openssl}" x509 \
|
|
||||||
-in "${opensk_cert_name}.pem" \
|
|
||||||
-outform der 2>/dev/null \
|
|
||||||
| xxd -i >> "${rust_file}"
|
|
||||||
echo "];" >> "${rust_file}"
|
|
||||||
echo "" >> "${rust_file}"
|
|
||||||
|
|
||||||
# Private key is tricky to extract as we want the raw value and not the DER encoding
|
|
||||||
# Example output of openssl ec -in file.key -noout -text:
|
|
||||||
# read EC key
|
|
||||||
# Private-Key: (256 bit)
|
|
||||||
# priv:
|
|
||||||
# 47:b3:58:b8:f0:09:1d:72:b1:03:34:62:9a:c7:b2:
|
|
||||||
# b2:e1:06:28:15:69:d4:82:b5:4e:21:6d:98:bf:65:
|
|
||||||
# 98:34
|
|
||||||
# pub:
|
|
||||||
# 04:32:84:a1:3c:90:db:3f:db:d7:fb:ff:e9:00:c8:
|
|
||||||
# 8a:a1:79:2e:95:2e:7c:86:ec:19:03:97:6e:7c:d6:
|
|
||||||
# 67:eb:28:56:f1:d8:dd:cb:ae:ce:b9:cb:e4:6d:9d:
|
|
||||||
# 1d:76:96:fc:48:9b:2d:d5:80:86:04:3d:f9:fe:6c:
|
|
||||||
# f3:9a:45:bc:b1
|
|
||||||
# ASN1 OID: prime256v1
|
|
||||||
# NIST CURVE: P-256
|
|
||||||
#
|
|
||||||
# The awk script starts printing lines after seeing a line starting with
|
|
||||||
# "priv:" and stops printing as soon as it reaches a line that doesn't start
|
|
||||||
# with a space.
|
|
||||||
# The sed script then converts the output into a proper hex-encode byte
|
|
||||||
# array by replacing the initial spaces on each line with "0x", replacing
|
|
||||||
# the semicolons at the end of each line by commas and replacing all
|
|
||||||
# remainging semicolons by ". 0x".
|
|
||||||
echo "pub const ATTESTATION_PRIVATE_KEY: [u8; 32] = [" >> "${rust_file}"
|
|
||||||
"${openssl}" ec \
|
|
||||||
-in "${opensk_key}" \
|
|
||||||
-noout \
|
|
||||||
-text 2>/dev/null \
|
|
||||||
| awk '/^priv:/{p=1;next}/^[^ ]/{p=0}p' \
|
|
||||||
| sed -e 's/^ */0x/;s/:$/,/;s/:/, 0x/g' >> "${rust_file}"
|
|
||||||
echo "];" >> "${rust_file}"
|
|
||||||
echo "" >> "${rust_file}"
|
|
||||||
|
|
||||||
# If the tool is installed, prettify the file. It will catch syntax errors earlier.
|
|
||||||
which rustfmt > /dev/null 2>&1 && rustfmt "${rust_file}"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user