diff --git a/samples/attestations/README.rst.in b/samples/attestations/README.rst.in new file mode 100644 index 00000000..3e188a17 --- /dev/null +++ b/samples/attestations/README.rst.in @@ -0,0 +1,19 @@ +# This file is used to generate README.rst + +product: + name: Google Cloud Key Management Service + short_name: Cloud Key Management Service + url: https://cloud.google.com/kms/docs/ + description: > + The `Cloud Key Management Service`_ allows you to create, import, and manage + cryptographic keys and perform cryptographic operations in a single centralized cloud service. + +setup: +- install_deps + +samples: +- name: Verify attestations for keys generated by Cloud HSM + file: verify_attestation.py + show_help: True + +folder: kms/attestations diff --git a/samples/attestations/requirements-test.txt b/samples/attestations/requirements-test.txt new file mode 100644 index 00000000..781d4326 --- /dev/null +++ b/samples/attestations/requirements-test.txt @@ -0,0 +1 @@ +pytest==5.3.2 diff --git a/samples/attestations/requirements.txt b/samples/attestations/requirements.txt new file mode 100644 index 00000000..036cf984 --- /dev/null +++ b/samples/attestations/requirements.txt @@ -0,0 +1,2 @@ +cryptography==2.8 +pem==20.1.0 diff --git a/samples/attestations/verify_attestation.py b/samples/attestations/verify_attestation.py new file mode 100644 index 00000000..69c16425 --- /dev/null +++ b/samples/attestations/verify_attestation.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +# Copyright 2020 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. + +"""This sample demonstrates how to verify HSM attestations using certificate +bundles obtained from Cloud HSM. + +For more information, visit https://cloud.google.com/kms/docs/attest-key. +""" + +# [START verify_attestations] +import gzip + +from cryptography import exceptions +from cryptography import x509 +from cryptography.hazmat import backends +from cryptography.hazmat.primitives.asymmetric import padding +import pem + + +def verify(attestation_file, bundle_file): + """Verifies an attestation using a bundle of certificates. + + Args: + attestation_file: The name of the attestation file. + bundle_file: The name of the bundle file containing the certificates + used to verify the attestation. + + Returns: + True if at least one of the certificates in bundle_file can verify the + attestation data and its signature. + """ + with gzip.open(attestation_file, 'rb') as f: + # An attestation file consists of a data portion and a 256 byte + # signature portion concatenated together. + attestation = f.read() + # Separate the components. + data = attestation[:-256] + signature = attestation[-256:] + + # Verify the attestation with one of the certificates in the bundle + for cert in pem.parse_file(bundle_file): + cert_obj = x509.load_pem_x509_certificate( + str(cert).encode('utf-8'), backends.default_backend()) + try: + # Check if the data was signed by the private key assosicated + # with the public key in the certificate. The data should have + # been signed with PKCS1v15 padding. + cert_obj.public_key().verify( + signature, data, padding.PKCS1v15(), + cert_obj.signature_hash_algorithm) + return True + except exceptions.InvalidSignature: + # Certificate bundles contain certificates that will not be + # able to verify the attestation, so the InvalidSignature + # errors can be ignored. + continue + return False +# [END verify_attestations] diff --git a/samples/attestations/verify_attestation_test.py b/samples/attestations/verify_attestation_test.py new file mode 100644 index 00000000..5cdc5ef2 --- /dev/null +++ b/samples/attestations/verify_attestation_test.py @@ -0,0 +1,109 @@ +# Copyright 2020 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. + +import tempfile + +import verify_attestation + +# Test certificate bundles can be generated with the following steps: +# 1. Generate test key pairs. +# - openssl genrsa -out test1.key 2048 +# - openssl genrsa -out test2.key 2048 +# 2. Generate test certificates using the key pairs. +# - openssl req -x509 -key test1.key -days 3650 -out test1.pem +# - openssl req -x509 -key test2.key -days 3650 -out test2.pem +# 3. Create a bundle using the test certificates. +# - cat test1.pem test2.pem > bundle.pem +# For instructions on downloading certificate bundles from Cloud HSM, refer to: +# https://cloud.google.com/kms/docs/attest-key#downloading_the_certificates +TEST_CERT_BUNDLE = b"""-----BEGIN CERTIFICATE----- +MIIDZDCCAkwCFE2PSNf++wMw+Jv86m41lbsa9aUMMA0GCSqGSIb3DQEBCwUAMFkx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCVRlc3QgQ2FyZDAeFw0yMDAz +MzEyMTQ0MjNaFw0zMDAzMjkyMTQ0MjNaMIGDMQswCQYDVQQGEwJBVTETMBEGA1UE +CAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk +MSMwIQYDVQQLDBpjbG91ZC1rbXMtcHJvZC11cy1jZW50cmFsMTEXMBUGA1UEAwwO +VGVzdCBQYXJ0aXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDh +cOk8hil8G4vl66jb02eXu2rKO6PmNF1GziXtzawyhx/+PDmEuGu+g/8hpivY6vDr +buAMFs8OIBBBlfED/soVANflXktDRGqWJau+rIrw9EGcclcwzlIboIi6KLPcLih0 +N0TTxqRLgy2EsEQ6UKS7su4bOIxD3Z6FSeTsoq+C2sgSWXmLitO0iRYYcgRjoyCU +kdzzO/JCwPKhhQx5NUrrHseALaIltG4D0aWLuBZKyV38yA1XEMdyCGk7RedEYC+v +OzaJrNToQBCIaCdn3F0uqJd49irLNPyQ5CY3NNL8rupJSq3iVxhEIZ8ANaU8UDvo +5iaQNKV1/KiQsXfUW6fbAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIIGB0aXhd6k +xyWgYzJ0DHpYP2ALwHRWXde5PtEkdHDguPlUTzZ5iTfqOJlEeUXlDO9RV82jc4mE +hguCaMl3Q+2JGLJLCnSDgcaY5WAVBF9FSakdbHBj4Ik9L8NDlUQB6Me4d4gKWpg1 +bUD4n2KtvCZGZzA3pfRBcYyAbwC+xEi1XrITyshb0pkjsWO4Urg36W/RpkCiYAw0 +Xua0jJMG/wcF+xktd7kgcsBh5Es2VCzyQwisXoOIi3EY7lMJK2+ctjQFy1GxumBU +jBlXj0VjAm3QOVLTh3mfb1XofoIjOOYkMBjXMiQhFy/Lv68u5q7qlEYe92OKxkCO +0UaAcqt8+QM= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDRjCCAi4CFBVm+eV+oRkaYq2NyuTfwxWapjFOMA0GCSqGSIb3DQEBCwUAMGYx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxHzAdBgNVBAMMFlRlc3QgTWFudWZhY3R1cmVy +IFJvb3QwHhcNMjAwMzMxMjE0MjU1WhcNMzAwMzI5MjE0MjU1WjBZMQswCQYDVQQG +EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk +Z2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlUZXN0IENhcmQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC28Wu0dusN6AYkYon8RIuHlJWWwZWlTxXSMK4v/IOY +pG9F2/gUEDMQOgpyCCpTc5eLHRPa/Z2QgB0c2VSlQC8FZ1l9/YL7uBTJ0UpDoBf8 +LUimIqotneXpL+7CW1kWFLZIgpm0iVuTPjV2b3frtvu0B+nYuyo4dtToebqoOKse +F3ymLsAjSqA9aoCD0XbspAkLJIvdQU28vXY4Y2y0OTGUnaQ7ZDwkNLxeAfeIdNJD +FRCcYsLRopsyptFMYLLDrI70gywAGYaGOxYG8747BIZELyT5Gnt0o7JwpuF8Mi53 +T5NGiu5/wLwXnxRRhb3M5+lStdTfvbEfgK1mC0ac8ym5AgMBAAEwDQYJKoZIhvcN +AQELBQADggEBAILH0Q8WlgaGBosPBjnpAsp4eZOfq9skKZERYzFA2wBAy4B0q9/S +3oL1MIZEU6/ckiFyAm3r4/ZxMLX0UrisuRQUFQ3w+gqFccqlmGETsZGJpPtfIm+n +JQo44XXnTHndqoYPNfvfQkp0WtJQS8hSgTASP+1GYjqOn1fZaa28m39/mx9Mrw7K +xtXOtrdKqJhWCWJPprfC5sYNCYTA2HXVmBU2Y4AP4A4w+A1gCAdzvH8EEyDjnvxJ +GEa4uczhA3n+NmhLipg1aGbxJO5ZHXdyFF2rTXVVXSiX8EEasnwcTDjeXDKhdpu6 +biaxW9fnsJIXirAE03FFkC/tWelkGFkmMfs= +-----END CERTIFICATE-----""" + +# Test attestations can be generated with the following steps: +# 1. Create a file containing the test attestation statement. +# - echo "content" > attestation.dat +# 2. Sign the file with one the key pairs used to create the test certificates. +# - openssl dgst -sha256 -sign test1.key -out signature.dat attestation.dat +# 3. Concatenate the signature to the statement to create an attestation. +# - cat signature.dat >> attestation.dat +# 4. Compress the test attestation. +# - gzip attestation.dat +# For instructions on downloading attestations from Cloud HSM, refer to: +# https://cloud.google.com/kms/docs/attest-key#downloading_the_attestation_statement +TEST_ATTESTATION_GZ = ( + b'\x1f\x8b\x08\x08\xda\xde\x84^\x00\x03attestation\x00\x01\x06\x01\xf9\xfe' + b'\x15\xa7~W\xdazHq03\x95\xd1F\xcf\x1d\n\xe0\xbbv\x11\xed\xae\x186\xc0\xcc' + b'.\xcf)\xf1?\xf7!\xf3\xd6M\x85\xfe\xb9\x84\xb2\x08V2(\xa1\x87]\xab\x01=' + b'\xb5\x0f)~\x06\xee\xfa/\x94\xa6x\x96o\xb1\xcb$\x82\x90\xe03J\t\x03\xf0' + b'\xa4\xa5\xa9\xf9\xb2\xce\xdd2\xfam\x94W\x07\x00~\xa5\xc2\xcdq\xa1\x81' + b'\x18\x83\xe0\xd9\x11k]\xbd\xf8\x81@\x9c*\x80\x91R\xb0\xae\x9d\x88\xb8T' + b'\xd1>\xf6;\xe4\x83q%_\x8aw\x894\xb5:\xeab\xd2\x9a\x81\xdd\xa6\xf9\x94' + b'\xff8\xb1\xed\x7fs\x0e\xc0\xde\x89\x00]\x8fL\x82\x8a\x11\x8f\\\xe483\x9d' + b'&\x0b%\xfd\x0et\x8f\xa8\x1a\xb5K\xb4\xc7\x96\xd1}\x06\xdd\x93i\x1f\xc1@' + b'\x92\xef}(B\x0f\xd1\x03\xaaYo\x9b\xad\xa9zw#\xc8\x9a\xad\x94\xfc\x07q]x' + b'\xeb\xa2CA\xf8\xac\x96\xd9\xe5y4\xae]\x81\xb0$\x93\tx\xdb\xcc\x08:%\x1d' + b'\xe2q\xaa\xc8:\xc2