1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
//nolint:unused // ignore unused types for now
package skae
import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"errors"
"math/big"
"github.com/smallstep/go-attestation/attest"
)
var (
oidSubjectKeyAttestationEvidence = asn1.ObjectIdentifier{2, 23, 133, 6, 1, 1} // SKAE (Subject Key Attestation Evidence) OID: 2.23.133.6.1.1
oidAuthorityInfoAccessOcsp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1}
oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2}
)
func CreateSubjectKeyAttestationEvidenceExtension(_ *x509.Certificate, _ attest.CertificationParameters, _ bool) (pkix.Extension, error) {
return pkix.Extension{}, errors.New("not implemented yet") // return early; not verified to be working as expected yet
/*
asn1Issuer, err := asn1.Marshal(akCert.Issuer.ToRDNSequence()) //nolint:govet // intentionally breaking early
if err != nil {
return pkix.Extension{}, fmt.Errorf("error marshaling issuer: %w", err)
}
skaeExtension := asn1SKAE{
TCGSpecVersion: asn1TCGSpecVersion{Major: 2, Minor: 0},
KeyAttestationEvidence: asn1KeyAttestationEvidence{},
}
attestationEvidence := asn1AttestationEvidence{
TPMCertifyInfo: asn1TPMCertifyInfo{
CertifyInfo: asn1.BitString{ // TODO: check if setting the values like this is correct
Bytes: params.CreateAttestation,
BitLength: len(params.CreateAttestation) * 8,
},
Signature: asn1.BitString{
Bytes: params.CreateSignature,
BitLength: len(params.CreateSignature) * 8,
},
},
TPMIdentityCredAccessInfo: asn1TPMIdentityCredentialAccessInfo{
AuthorityInfoAccess: createAIA(akCert),
IssuerSerial: issuerAndSerial{
IssuerName: asn1.RawValue{FullBytes: asn1Issuer},
SerialNumber: akCert.SerialNumber,
},
},
}
aeb, err := asn1.Marshal(attestationEvidence)
if err != nil {
return pkix.Extension{}, fmt.Errorf("error marshaling attestation evidence: %w", err)
}
if !shouldEncrypt {
//skaeExtension.KeyAttestationEvidence.AttestEvidence = attestationEvidence
skaeExtension.KeyAttestationEvidence.Evidence = asn1.RawValue{
Class: asn1.ClassContextSpecific,
IsCompound: true,
Tag: 0, // CHOICE "0"
Bytes: aeb,
}
} else {
// TODO: encrypt the AttestEvidence to (right) recipient; set it as the EnvelopedAttestEvidence
encryptedAEB := aeb
eae := asn1EnvelopedAttestationEvidence{
RecipientInfos: []recipientInfo{}, // TODO: fill recipient(s)
EncryptedAttestInfo: asn1EncryptedAttestationInfo{
EncryptionAlgorithm: pkix.AlgorithmIdentifier{
Algorithm: nil, // TODO: select and fill
},
EncryptedAttestEvidence: encryptedAEB,
},
}
eaeBytes, err := asn1.Marshal(eae)
if err != nil {
return pkix.Extension{}, errors.New("error marshaling EnvelopedAttestationEvidence")
}
skaeExtension.KeyAttestationEvidence.Evidence = asn1.RawValue{
Class: asn1.ClassContextSpecific,
IsCompound: true,
Tag: 1, // CHOICE "1"
Bytes: eaeBytes,
}
return pkix.Extension{}, errors.New("encrypting the AttestEvidence is not yet supported")
}
skaeExtensionBytes, err := asn1.Marshal(skaeExtension)
if err != nil {
return pkix.Extension{}, fmt.Errorf("creating SKAE extension failed: %w", err)
}
result := pkix.Extension{
Id: oidSubjectKeyAttestationEvidence,
Critical: false, // non standard extension; don't break clients
Value: skaeExtensionBytes,
}
b, err := asn1.Marshal(result)
if err != nil {
return result, err
}
_ = b
return result, nil
*/
}
func createAIA(ak *x509.Certificate) []asn1AuthorityInfoAccessSyntax {
var aiaValues []asn1AuthorityInfoAccessSyntax
for _, server := range ak.OCSPServer {
aiaValues = append(aiaValues, asn1AuthorityInfoAccessSyntax{
Method: oidAuthorityInfoAccessOcsp,
Location: asn1.RawValue{Tag: asn1.TagOID, Class: asn1.ClassContextSpecific, Bytes: []byte(server)},
})
}
for _, url := range ak.IssuingCertificateURL {
aiaValues = append(aiaValues, asn1AuthorityInfoAccessSyntax{
Method: oidAuthorityInfoAccessIssuers,
Location: asn1.RawValue{Tag: asn1.TagOID, Class: asn1.ClassContextSpecific, Bytes: []byte(url)},
})
}
return aiaValues
}
type asn1SKAE struct {
TCGSpecVersion asn1TCGSpecVersion
KeyAttestationEvidence asn1KeyAttestationEvidence
}
type asn1TCGSpecVersion struct {
Major int
Minor int
}
type asn1KeyAttestationEvidence struct {
// AttestEvidence asn1AttestationEvidence // TODO: ASN1 CHOICE between those two
// EnvelopedAttestEvidence asn1EnvelopedAttestationEvidence
Evidence asn1.RawValue
}
type asn1AttestationEvidence struct {
TPMCertifyInfo asn1TPMCertifyInfo
TPMIdentityCredAccessInfo asn1TPMIdentityCredentialAccessInfo
}
type asn1TPMCertifyInfo struct {
CertifyInfo asn1.BitString
Signature asn1.BitString
}
type asn1TPMIdentityCredentialAccessInfo struct {
AuthorityInfoAccess []asn1AuthorityInfoAccessSyntax
IssuerSerial issuerAndSerial
}
type asn1AuthorityInfoAccessSyntax struct {
Method asn1.ObjectIdentifier
Location asn1.RawValue
}
type issuerAndSerial struct {
IssuerName asn1.RawValue
SerialNumber *big.Int
}
type asn1EnvelopedAttestationEvidence struct {
RecipientInfos []recipientInfo `asn1:"set"`
EncryptedAttestInfo asn1EncryptedAttestationInfo
}
type recipientInfo struct {
Version int
IssuerAndSerialNumber issuerAndSerial
KeyEncryptionAlgorithm pkix.AlgorithmIdentifier
EncryptedKey []byte
}
type asn1EncryptedAttestationInfo struct {
EncryptionAlgorithm pkix.AlgorithmIdentifier
EncryptedAttestEvidence []byte // -- The ciphertext resulting from the encryption of DER-encoded AttestationEvidence (against public key in recipientinfo; something like that)
}
|