pkinit: Fix asn1 structures and add tests that ensures that they can be serialized

This commit is contained in:
Erik Geiser
2026-05-12 16:24:17 +02:00
parent 3d18e8a5a6
commit 54e2981767
3 changed files with 113 additions and 6 deletions
+4 -4
View File
@@ -23,7 +23,7 @@ var (
)
type SignerInfo struct {
Version uint64 `asn1:"default:1"`
Version int `asn1:"default:1"`
IssuerAndSerialNumber IssuerAndSerial
DigestAlgorithm pkix.AlgorithmIdentifier
AuthenticatedAttributes []Attribute `asn1:"optional,omitempty,tag:0"`
@@ -48,7 +48,7 @@ type ContentInfo struct {
}
type SignedData struct {
Version uint64 `asn1:"default:1"`
Version int `asn1:"default:1"`
DigestAlgorithmIdentifiers []pkix.AlgorithmIdentifier `asn1:"set"`
ContentInfo ContentInfo
Certificates RawCertificates `asn1:"optional,tag:0"`
@@ -95,9 +95,9 @@ type PKAuthenticator struct {
// paChecksum [3] OCTET STRING OPTIONAL,
// ...
// asn1
CUSec uint32 `asn1:"tag:0,explicit"`
CUSec int `asn1:"tag:0,explicit"`
CTime time.Time `asn1:"tag:1,explicit,generalized"`
Nonce uint32 `asn1:"tag:2,explicit"`
Nonce int `asn1:"tag:2,explicit"`
Checksum []byte `asn1:"tag:3,explicit,optional"`
}
+107
View File
@@ -0,0 +1,107 @@
package pkinit
import (
"crypto/x509/pkix"
"encoding/asn1"
"fmt"
"math/big"
"testing"
"time"
)
func TestASN1Marshal(t *testing.T) {
// just a simple asn1.Marshal test that ensures that the asn1 structs do not
// contain unexpected types (like uint32 instead of int) that only cause
// errors at runtime.
tests := []any{
SignerInfo{
Version: 1,
IssuerAndSerialNumber: IssuerAndSerial{
IssuerName: asn1.RawValue{},
SerialNumber: big.NewInt(12345),
},
DigestAlgorithm: pkix.AlgorithmIdentifier{
Algorithm: asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 5},
Parameters: asn1.RawValue{Tag: 5},
},
DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{
Algorithm: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1},
Parameters: asn1.RawValue{Tag: 5},
},
EncryptedDigest: []byte("signature"),
},
Attribute{
Type: asn1.ObjectIdentifier{1, 2, 3},
Value: asn1.RawValue{},
},
IssuerAndSerial{
IssuerName: asn1.RawValue{Tag: 16 /* SEQUENCE */},
SerialNumber: big.NewInt(67890),
},
ContentInfo{
ContentType: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2},
},
SignedData{
Version: 1,
ContentInfo: ContentInfo{
ContentType: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2},
},
SignerInfos: []SignerInfo{},
},
RawCertificates{
Raw: []byte{0x30, 0x03, 0x01, 0x00, 0x00},
},
AuthPack{
PKAuthenticator: PKAuthenticator{
CUSec: 123,
CTime: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC),
Nonce: 42,
Checksum: []byte("checksum"),
},
},
PKAuthenticator{
CUSec: 123,
CTime: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC),
Nonce: 42,
Checksum: []byte("checksum"),
},
SubjectPublicKeyInfo{
Algorithm: AlgorithmIdentifier{
Algorithm: asn1.ObjectIdentifier{1, 2, 840, 10046, 2, 1},
},
PublicKey: asn1.BitString{Bytes: []byte{0x04}, BitLength: 8},
},
AlgorithmIdentifier{
Algorithm: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1},
},
DomainParameters{
P: big.NewInt(23),
G: 5,
Q: 11,
},
PAPKASRep{
DHInfo: asn1.RawValue{},
},
PAPACRequest{
IncludePAC: true,
},
DHRepInfo{
DHSignedData: []byte("data"),
ServerDHNonce: []byte("nonce"),
},
KDCDHKeyInfo{
SubjectPublicKey: asn1.BitString{Bytes: []byte{0x04}, BitLength: 8},
Nonce: big.NewInt(999),
DHKeyExpication: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC),
},
}
for _, val := range tests {
t.Run(fmt.Sprintf("%T", val), func(t *testing.T) {
_, err := asn1.MarshalWithParams(val, "")
if err != nil {
t.Errorf("asn1.Marshal() failed for %T: %v", val, err)
}
})
}
}
+2 -2
View File
@@ -51,9 +51,9 @@ func ConfigureASReq(
authPack := AuthPack{
PKAuthenticator: PKAuthenticator{
CUSec: uint32(now.UnixMicro() - now.Truncate(time.Millisecond).UnixMicro()),
CUSec: int(now.UnixMicro() - now.Truncate(time.Millisecond).UnixMicro()),
CTime: now,
Nonce: mathRand.Uint32(), //nolint:gosec
Nonce: int(mathRand.Uint32()), //nolint:gosec
Checksum: pkAuthenticatorChecksum,
},
ClientPublicValue: SubjectPublicKeyInfo{