Skip to content

Commit b3bc6f7

Browse files
SECENG-13957: fix: add ML-DSA support to bundler, initca renewal, and display functions
- bundler: accept ML-DSA certs in Bundle() key validation (key-present and keyless paths), add MLDSA key type and PKCS#8 serialization to MarshalJSON - initca: add ML-DSA case to RenewFromSigner() key matching - helpers: KeyLength() returns public key byte size (1312/1952/2592) per PQC func spec; SignatureString() and HashAlgoString() return MLDSA44/65/87 instead of "Unknown"
1 parent 3f8cf50 commit b3bc6f7

4 files changed

Lines changed: 47 additions & 0 deletions

File tree

‎bundler/bundle.go‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"crypto/ecdsa"
66
"crypto/ed25519"
7+
"crypto/mldsa"
78
"crypto/rsa"
89
"crypto/x509"
910
"crypto/x509/pkix"
@@ -112,6 +113,8 @@ func (b *Bundle) MarshalJSON() ([]byte, error) {
112113
keyType = "DSA"
113114
case x509.Ed25519:
114115
keyType = "Ed25519"
116+
case x509.MLDSA:
117+
keyType = fmt.Sprintf("%d-byte ML-DSA", keyLength)
115118
default:
116119
keyType = "Unknown"
117120
}
@@ -126,6 +129,9 @@ func (b *Bundle) MarshalJSON() ([]byte, error) {
126129
case ed25519.PrivateKey:
127130
keyBytes, _ = derhelpers.MarshalEd25519PrivateKey(key)
128131
keyString = PemBlockToString(&pem.Block{Type: "Ed25519 PRIVATE KEY", Bytes: keyBytes})
132+
case *mldsa.PrivateKey:
133+
keyBytes, _ = x509.MarshalPKCS8PrivateKey(key)
134+
keyString = PemBlockToString(&pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes})
129135
case fmt.Stringer:
130136
keyString = key.String()
131137
}

‎bundler/bundler.go‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"crypto"
88
"crypto/ecdsa"
99
"crypto/ed25519"
10+
"crypto/mldsa"
1011
"crypto/rsa"
1112
"crypto/tls"
1213
"crypto/x509"
@@ -597,6 +598,14 @@ func (b *Bundler) Bundle(certs []*x509.Certificate, key crypto.Signer, flavor Bu
597598
if !(bytes.Equal(cert.PublicKey.(ed25519.PublicKey), ed25519PublicKey)) {
598599
return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
599600
}
601+
case cert.PublicKeyAlgorithm == x509.MLDSA:
602+
var mldsaPublicKey *mldsa.PublicKey
603+
if mldsaPublicKey, ok = key.Public().(*mldsa.PublicKey); !ok {
604+
return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
605+
}
606+
if !cert.PublicKey.(*mldsa.PublicKey).Equal(mldsaPublicKey) {
607+
return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
608+
}
600609
default:
601610
return nil, errors.New(errors.PrivateKeyError, errors.NotRSAOrECCOrEd25519)
602611
}
@@ -605,6 +614,7 @@ func (b *Bundler) Bundle(certs []*x509.Certificate, key crypto.Signer, flavor Bu
605614
case cert.PublicKeyAlgorithm == x509.RSA:
606615
case cert.PublicKeyAlgorithm == x509.ECDSA:
607616
case cert.PublicKeyAlgorithm == x509.Ed25519:
617+
case cert.PublicKeyAlgorithm == x509.MLDSA:
608618
default:
609619
return nil, errors.New(errors.PrivateKeyError, errors.NotRSAOrECCOrEd25519)
610620
}

‎helpers/helpers.go‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ func KeyLength(key interface{}) int {
7474
return rsaKey.N.BitLen()
7575
} else if _, ok := key.(ed25519.PublicKey); ok {
7676
return ed25519.PublicKeySize
77+
} else if mldsaKey, ok := key.(*mldsa.PublicKey); ok {
78+
switch {
79+
case mldsaKey.Parameters() == mldsa.MLDSA44():
80+
return 1312
81+
case mldsaKey.Parameters() == mldsa.MLDSA65():
82+
return 1952
83+
case mldsaKey.Parameters() == mldsa.MLDSA87():
84+
return 2592
85+
}
7786
}
7887

7988
return 0
@@ -157,6 +166,12 @@ func SignatureString(alg x509.SignatureAlgorithm) string {
157166
return "ECDSAWithSHA512"
158167
case x509.PureEd25519:
159168
return "Ed25519"
169+
case x509.MLDSA44:
170+
return "MLDSA44"
171+
case x509.MLDSA65:
172+
return "MLDSA65"
173+
case x509.MLDSA87:
174+
return "MLDSA87"
160175
default:
161176
return "Unknown Signature"
162177
}
@@ -192,6 +207,12 @@ func HashAlgoString(alg x509.SignatureAlgorithm) string {
192207
return "SHA512"
193208
case x509.PureEd25519:
194209
return "Ed25519"
210+
case x509.MLDSA44:
211+
return "MLDSA44"
212+
case x509.MLDSA65:
213+
return "MLDSA65"
214+
case x509.MLDSA87:
215+
return "MLDSA87"
195216
default:
196217
return "Unknown Hash Algorithm"
197218
}

‎initca/initca.go‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"crypto"
88
"crypto/ecdsa"
99
"crypto/ed25519"
10+
"crypto/mldsa"
1011
"crypto/rand"
1112
"crypto/rsa"
1213
"crypto/x509"
@@ -220,6 +221,15 @@ func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) {
220221
if !(bytes.Equal(ca.PublicKey.(ed25519.PublicKey), ed25519PublicKey)) {
221222
return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
222223
}
224+
case ca.PublicKeyAlgorithm == x509.MLDSA:
225+
var mldsaPublicKey *mldsa.PublicKey
226+
var ok bool
227+
if mldsaPublicKey, ok = priv.Public().(*mldsa.PublicKey); !ok {
228+
return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
229+
}
230+
if !ca.PublicKey.(*mldsa.PublicKey).Equal(mldsaPublicKey) {
231+
return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
232+
}
223233
default:
224234
return nil, cferr.New(cferr.PrivateKeyError, cferr.NotRSAOrECCOrEd25519)
225235
}

0 commit comments

Comments
 (0)