@@ -21,6 +21,7 @@ import (
2121 "crypto/ed25519"
2222 "crypto/elliptic"
2323 "crypto/rand"
24+ "crypto/rsa"
2425 "crypto/x509"
2526 "encoding/binary"
2627 "errors"
@@ -40,6 +41,10 @@ const (
4041 dcMaxSignatureLen = (1 << 16 ) - 1 // Bytes
4142)
4243
44+ const (
45+ undefinedSignatureScheme SignatureScheme = 0x0000
46+ )
47+
4348var extensionDelegatedCredential = []int {1 , 3 , 6 , 1 , 4 , 1 , 44363 , 44 }
4449
4550// isValidForDelegation returns true if a certificate can be used for Delegated
@@ -61,7 +66,6 @@ func isValidForDelegation(cert *x509.Certificate) bool {
6166 return true
6267 }
6368 }
64-
6569 return false
6670}
6771
@@ -133,6 +137,7 @@ func (cred *credential) marshalPublicKeyInfo() ([]byte, error) {
133137 }
134138
135139 return rawPub , nil
140+
136141 default :
137142 return nil , fmt .Errorf ("tls: unsupported signature scheme: 0x%04x" , cred .expCertVerfAlgo )
138143 }
@@ -228,6 +233,12 @@ func getHash(scheme SignatureScheme) crypto.Hash {
228233 return crypto .SHA512
229234 case Ed25519 :
230235 return directSigning
236+ case PKCS1WithSHA256 , PSSWithSHA256 :
237+ return crypto .SHA256
238+ case PSSWithSHA384 :
239+ return crypto .SHA384
240+ case PSSWithSHA512 :
241+ return crypto .SHA512
231242 default :
232243 return 0 //Unknown hash function
233244 }
@@ -291,28 +302,29 @@ func prepareDelegationSignatureInput(hash crypto.Hash, cred *credential, dCert [
291302// Extract the algorithm used to sign the Delegated Credential from the
292303// end-entity (leaf) certificate.
293304func getSignatureAlgorithm (cert * Certificate ) (SignatureScheme , error ) {
294- var sigAlgo SignatureScheme
295305 switch sk := cert .PrivateKey .(type ) {
296306 case * ecdsa.PrivateKey :
297307 pk := sk .Public ().(* ecdsa.PublicKey )
298308 curveName := pk .Curve .Params ().Name
299- certAlg := cert .Leaf .SignatureAlgorithm
300- if certAlg == x509 .ECDSAWithSHA256 && curveName == "P-256" {
301- sigAlgo = ECDSAWithP256AndSHA256
302- } else if certAlg == x509 .ECDSAWithSHA384 && curveName == "P-384" {
303- sigAlgo = ECDSAWithP384AndSHA384
304- } else if certAlg == x509 .ECDSAWithSHA512 && curveName == "P-521" {
305- sigAlgo = ECDSAWithP521AndSHA512
309+ certAlg := cert .Leaf .PublicKeyAlgorithm
310+ if certAlg == x509 .ECDSA && curveName == "P-256" {
311+ return ECDSAWithP256AndSHA256 , nil
312+ } else if certAlg == x509 .ECDSA && curveName == "P-384" {
313+ return ECDSAWithP384AndSHA384 , nil
314+ } else if certAlg == x509 .ECDSA && curveName == "P-521" {
315+ return ECDSAWithP521AndSHA512 , nil
306316 } else {
307- return SignatureScheme ( 0x00 ) , fmt .Errorf ("using curve %s for %s is not supported" , curveName , cert .Leaf .SignatureAlgorithm )
317+ return undefinedSignatureScheme , fmt .Errorf ("using curve %s for %s is not supported" , curveName , cert .Leaf .SignatureAlgorithm )
308318 }
309319 case ed25519.PrivateKey :
310- sigAlgo = Ed25519
320+ return Ed25519 , nil
321+ case * rsa.PrivateKey :
322+ // If the certificate has the RSAEncryption OID there are a number of valid signature schemes that may sign the DC.
323+ // In the absence of better information, we make a reasonable choice.
324+ return PSSWithSHA256 , nil
311325 default :
312- return SignatureScheme ( 0x00 ) , fmt .Errorf ("tls: unsupported algorithm for Delegated Credential" )
326+ return undefinedSignatureScheme , fmt .Errorf ("tls: unsupported algorithm for signing Delegated Credential" )
313327 }
314-
315- return sigAlgo , nil
316328}
317329
318330// NewDelegatedCredential creates a new Delegated Credential using 'cert' for
@@ -365,7 +377,7 @@ func NewDelegatedCredential(cert *Certificate, pubAlgo SignatureScheme, validTim
365377 return nil , nil , err
366378 }
367379 default :
368- return nil , nil , fmt .Errorf ("tls: unsupported algorithm for Delegated Credential: %T " , pubAlgo )
380+ return nil , nil , fmt .Errorf ("tls: unsupported algorithm for Delegated Credential: %s " , pubAlgo )
369381 }
370382
371383 // Prepare the credential for signing
@@ -390,6 +402,13 @@ func NewDelegatedCredential(cert *Certificate, pubAlgo SignatureScheme, validTim
390402 if err != nil {
391403 return nil , nil , err
392404 }
405+ case * rsa.PrivateKey :
406+ opts := & rsa.PSSOptions {SaltLength : rsa .PSSSaltLengthEqualsHash ,
407+ Hash : hash }
408+ sig , err = rsa .SignPSS (rand .Reader , sk , hash , values , opts )
409+ if err != nil {
410+ return nil , nil , err
411+ }
393412 default :
394413 return nil , nil , fmt .Errorf ("tls: unsupported key type for Delegated Credential" )
395414 }
@@ -448,17 +467,29 @@ func (dc *DelegatedCredential) Validate(cert *x509.Certificate, isClient bool, n
448467 }
449468
450469 return ed25519 .Verify (pk , in , dc .signature )
470+ case PSSWithSHA256 ,
471+ PSSWithSHA384 ,
472+ PSSWithSHA512 :
473+ pk , ok := cert .PublicKey .(* rsa.PublicKey )
474+ if ! ok {
475+ return false
476+ }
477+ hash := getHash (dc .algorithm )
478+ return rsa .VerifyPSS (pk , hash , in , dc .signature , nil ) == nil
451479 default :
452480 return false
453481 }
454482}
455483
456- // marshal encodes a DelegatedCredential structure. It also sets dc.Raw to that
484+ // Marshal encodes a DelegatedCredential structure. It also sets dc.Raw to that
457485// encoding.
458- func (dc * DelegatedCredential ) marshal () ([]byte , error ) {
486+ func (dc * DelegatedCredential ) Marshal () ([]byte , error ) {
459487 if len (dc .signature ) > dcMaxSignatureLen {
460488 return nil , errors .New ("tls: delegated credential is not valid" )
461489 }
490+ if len (dc .signature ) == 0 {
491+ return nil , errors .New ("tls: delegated credential has no signature" )
492+ }
462493
463494 raw , err := dc .cred .marshal ()
464495 if err != nil {
@@ -475,8 +506,8 @@ func (dc *DelegatedCredential) marshal() ([]byte, error) {
475506 return dc .raw , nil
476507}
477508
478- // unmarshalDelegatedCredential decodes a DelegatedCredential structure.
479- func unmarshalDelegatedCredential (raw []byte ) (* DelegatedCredential , error ) {
509+ // UnmarshalDelegatedCredential decodes a DelegatedCredential structure.
510+ func UnmarshalDelegatedCredential (raw []byte ) (* DelegatedCredential , error ) {
480511 rawCredentialLen , err := getCredentialLen (raw )
481512 if err != nil {
482513 return nil , err
0 commit comments