Skip to content

Commit 66f7d5d

Browse files
author
Daniel
committed
local: generate lintPriv key when required by profiles.
1 parent 787a454 commit 66f7d5d

File tree

2 files changed

+79
-7
lines changed

2 files changed

+79
-7
lines changed

signer/local/local.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ package local
44
import (
55
"bytes"
66
"crypto"
7+
"crypto/ecdsa"
8+
"crypto/elliptic"
79
"crypto/rand"
810
"crypto/x509"
911
"crypto/x509/pkix"
@@ -35,8 +37,11 @@ import (
3537
// Signer contains a signer that uses the standard library to
3638
// support both ECDSA and RSA CA keys.
3739
type Signer struct {
38-
ca *x509.Certificate
39-
priv crypto.Signer
40+
ca *x509.Certificate
41+
priv crypto.Signer
42+
// lintPriv is generated randomly when pre-issuance linting is configured and
43+
// used to sign TBSCertificates for linting.
44+
lintPriv crypto.Signer
4045
policy *config.Signing
4146
sigAlgo x509.SignatureAlgorithm
4247
dbAccessor certdb.Accessor
@@ -55,11 +60,30 @@ func NewSigner(priv crypto.Signer, cert *x509.Certificate, sigAlgo x509.Signatur
5560
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
5661
}
5762

63+
var lintPriv crypto.Signer
64+
// If there is at least one profile that configures pre-issuance linting then
65+
// generate the one-off lintPriv key.
66+
for _, profile := range policy.Profiles {
67+
if profile.LintErrLevel > 0 || policy.Default.LintErrLevel > 0 {
68+
// In the future there may be demand for specifying the type of signer used
69+
// for pre-issuance linting in configuration. For now we assume that signing
70+
// with a randomly generated P-256 ECDSA private key is acceptable for all cases
71+
// where linting is requested.
72+
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
73+
if err != nil {
74+
return nil, cferr.New(cferr.PrivateKeyError, cferr.GenerationFailed)
75+
}
76+
lintPriv = k
77+
break
78+
}
79+
}
80+
5881
return &Signer{
59-
ca: cert,
60-
priv: priv,
61-
sigAlgo: sigAlgo,
62-
policy: policy,
82+
ca: cert,
83+
priv: priv,
84+
lintPriv: lintPriv,
85+
sigAlgo: sigAlgo,
86+
policy: policy,
6387
}, nil
6488
}
6589

signer/local/local_test.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,13 @@ func TestNewSignerFromFilePolicy(t *testing.T) {
6969
},
7070
},
7171
}
72-
_, err := NewSignerFromFile(testCaFile, testCaKeyFile, CAConfig.Signing)
72+
signer, err := NewSignerFromFile(testCaFile, testCaKeyFile, CAConfig.Signing)
7373
if err != nil {
7474
t.Fatal(err)
7575
}
76+
if signer.lintPriv != nil {
77+
t.Error("expected signer with LintErrLevel == 0 to have lintPriv == nil")
78+
}
7679
}
7780

7881
func TestNewSignerFromFileInvalidPolicy(t *testing.T) {
@@ -150,6 +153,51 @@ func TestNewSignerFromFileEdgeCases(t *testing.T) {
150153
}
151154
}
152155

156+
func TestNewSignerFromFilePolicyLinting(t *testing.T) {
157+
// CAConfig is a config that has an explicit "signature" profile that enables
158+
// pre-issuance linting.
159+
var CAConfig = &config.Config{
160+
Signing: &config.Signing{
161+
Profiles: map[string]*config.SigningProfile{
162+
"signature": {
163+
Usage: []string{"digital signature"},
164+
Expiry: expiry,
165+
LintErrLevel: 3,
166+
},
167+
},
168+
Default: &config.SigningProfile{
169+
Usage: []string{"cert sign", "crl sign"},
170+
ExpiryString: "43800h",
171+
Expiry: expiry,
172+
CAConstraint: config.CAConstraint{IsCA: true},
173+
},
174+
},
175+
}
176+
signer, err := NewSignerFromFile(testCaFile, testCaKeyFile, CAConfig.Signing)
177+
if err != nil {
178+
t.Fatal(err)
179+
}
180+
// A CAConfig with a signing profile that sets LintErrLevel > 0 should have
181+
// a lintPriv key generated.
182+
if signer.lintPriv == nil {
183+
t.Error("expected signer with profile LintErrLevel > 0 to have lintPriv != nil")
184+
}
185+
186+
// Reconfigure caConfig so that the explicit "signature" profile doesn't
187+
// enable pre-issuance linting but the default profile does.
188+
CAConfig.Signing.Profiles["signature"].LintErrLevel = 0
189+
CAConfig.Signing.Default.LintErrLevel = 3
190+
signer, err = NewSignerFromFile(testCaFile, testCaKeyFile, CAConfig.Signing)
191+
if err != nil {
192+
t.Fatal(err)
193+
}
194+
// A CAConfig with a default profile that sets LintErrLevel > 0 should have
195+
// a lintPriv key generated.
196+
if signer.lintPriv == nil {
197+
t.Error("expected signer with default profile LintErrLevel > 0 to have lintPriv != nil")
198+
}
199+
}
200+
153201
func TestSign(t *testing.T) {
154202
s, err := NewSignerFromFile("testdata/ca.pem", "testdata/ca_key.pem", nil)
155203
if err != nil {

0 commit comments

Comments
 (0)