Noel Georgi 166d75fe88
fix: tpm2 encrypt/decrypt flow
The previous flow was using TPM PCR 11 values to bound the policy which
means TPM cannot unseal when UKI changes. Now it's fixed to use PCR 7
which is bound to the SecureBoot state (SecureBoot status and
Certificates). This provides a full chain of trust bound to SecureBoot
state and signed PCR signature.

Also the code has been refactored to use PolicyCalculator from the TPM
library.

Signed-off-by: Noel Georgi <git@frezbo.dev>
2023-07-14 23:58:59 +05:30

87 lines
2.2 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package measure contains Go implementation of 'systemd-measure' command.
//
// This implements TPM PCR emulation, UKI signature measurement, signing the measured values.
package measure
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
"github.com/google/go-tpm/tpm2"
"github.com/siderolabs/talos/internal/pkg/secureboot"
"github.com/siderolabs/talos/internal/pkg/secureboot/measure/internal/pcr"
tpm2internal "github.com/siderolabs/talos/internal/pkg/secureboot/tpm2"
)
// SectionsData holds a map of Section to file path to the corresponding section.
type SectionsData map[secureboot.Section]string
func loadRSAKey(path string) (*rsa.PrivateKey, error) {
keyData, err := os.ReadFile(path)
if err != nil {
return nil, err
}
// convert private key to rsa.PrivateKey
rsaPrivateKeyBlock, _ := pem.Decode(keyData)
if rsaPrivateKeyBlock == nil {
return nil, err
}
rsaKey, err := x509.ParsePKCS1PrivateKey(rsaPrivateKeyBlock.Bytes)
if err != nil {
return nil, fmt.Errorf("parse private key failed: %v", err)
}
return rsaKey, nil
}
// GenerateSignedPCR generates the PCR signed data for a given set of UKI file sections.
func GenerateSignedPCR(sectionsData SectionsData, rsaKeyPath string) (*tpm2internal.PCRData, error) {
rsaKey, err := loadRSAKey(rsaKeyPath)
if err != nil {
return nil, err
}
data := &tpm2internal.PCRData{}
for _, algo := range []struct {
alg tpm2.TPMAlgID
bankDataSetter *[]tpm2internal.BankData
}{
{
alg: tpm2.TPMAlgSHA1,
bankDataSetter: &data.SHA1,
},
{
alg: tpm2.TPMAlgSHA256,
bankDataSetter: &data.SHA256,
},
{
alg: tpm2.TPMAlgSHA384,
bankDataSetter: &data.SHA384,
},
{
alg: tpm2.TPMAlgSHA512,
bankDataSetter: &data.SHA512,
},
} {
bankData, err := pcr.CalculateBankData(secureboot.UKIPCR, algo.alg, sectionsData, rsaKey)
if err != nil {
return nil, err
}
*algo.bankDataSetter = bankData
}
return data, nil
}