Skip to content

Commit

Permalink
Check role key type and bits when signing CSR.
Browse files Browse the repository at this point in the history
Two exceptions: signing an intermediate CA CSR, and signing a CSR via
the 'sign-verbatim' path.
  • Loading branch information
jefferai committed Feb 20, 2016
1 parent 9f5d45d commit 5da2949
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 1 deletion.
57 changes: 56 additions & 1 deletion builtin/logical/pki/cert_util.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pki

import (
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
Expand Down Expand Up @@ -437,14 +438,68 @@ func signCert(b *backend,
return nil, certutil.UserError{Err: "certificate request could not be parsed"}
}

if csr.PublicKeyAlgorithm == x509.RSA {
switch role.KeyType {
case "rsa":
// Verify that the key matches the role type
if csr.PublicKeyAlgorithm != x509.RSA {
return nil, certutil.UserError{Err: fmt.Sprintf(
"role requires keys of type %s",
role.KeyType)}
}
pubKey, ok := csr.PublicKey.(*rsa.PublicKey)
if !ok {
return nil, certutil.UserError{Err: "could not parse CSR's public key"}
}

// Verify that the key is at least 2048 bits
if pubKey.N.BitLen() < 2048 {
return nil, certutil.UserError{Err: "RSA keys < 2048 bits are unsafe and not supported"}
}

// Verify that the bit size is at least the size specified in the role
if pubKey.N.BitLen() < role.KeyBits {
return nil, certutil.UserError{Err: fmt.Sprintf(
"role requires a minimum of a %d-bit key, but CSR's key is %d bits",
role.KeyBits,
pubKey.N.BitLen())}
}

case "ec":
// Verify that the key matches the role type
if csr.PublicKeyAlgorithm != x509.ECDSA {
return nil, certutil.UserError{Err: fmt.Sprintf(
"role requires keys of type %s",
role.KeyType)}
}
pubKey, ok := csr.PublicKey.(*ecdsa.PublicKey)
if !ok {
return nil, certutil.UserError{Err: "could not parse CSR's public key"}
}

// Verify that the bit size is at least the size specified in the role
if pubKey.Params().BitSize < role.KeyBits {
return nil, certutil.UserError{Err: fmt.Sprintf(
"role requires a minimum of a %d-bit key, but CSR's key is %d bits",
role.KeyBits,
pubKey.Params().BitSize)}
}

case "any":
// We only care about running RSA < 2048 bit checks, so if not RSA
// break out
if csr.PublicKeyAlgorithm != x509.RSA {
break
}

// Run RSA < 2048 bit checks
pubKey, ok := csr.PublicKey.(*rsa.PublicKey)
if !ok {
return nil, certutil.UserError{Err: "could not parse CSR's public key"}
}
if pubKey.N.BitLen() < 2048 {
return nil, certutil.UserError{Err: "RSA keys < 2048 bits are unsafe and not supported"}
}

}

creationBundle, err := generateCreationBundle(b, role, signingBundle, csr, req, data)
Expand Down
1 change: 1 addition & 0 deletions builtin/logical/pki/path_issue_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func (b *backend) pathSignVerbatim(
AllowAnyName: true,
AllowIPSANs: true,
EnforceHostnames: false,
KeyType: "any",
}

return b.pathIssueSignCert(req, data, role, true, true)
Expand Down
1 change: 1 addition & 0 deletions builtin/logical/pki/path_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ func (b *backend) pathCASignIntermediate(
AllowAnyName: true,
AllowIPSANs: true,
EnforceHostnames: false,
KeyType: "any",
}

if cn := data.Get("common_name").(string); len(cn) == 0 {
Expand Down

0 comments on commit 5da2949

Please sign in to comment.