-
Notifications
You must be signed in to change notification settings - Fork 51
/
pkisecrets.go
167 lines (134 loc) · 4.17 KB
/
pkisecrets.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package secrets
import (
"crypto/ecdsa"
"crypto/x509"
"errors"
"fmt"
"go.uber.org/zap"
"github.com/aporeto-inc/trireme-lib/utils/crypto"
)
// PKISecrets holds all PKI information
type PKISecrets struct {
PrivateKeyPEM []byte
PublicKeyPEM []byte
AuthorityPEM []byte
CertificateCache map[string]*ecdsa.PublicKey
privateKey *ecdsa.PrivateKey
publicKey *x509.Certificate
certPool *x509.CertPool
}
// NewPKISecrets creates new secrets for PKI implementations
func NewPKISecrets(keyPEM, certPEM, caPEM []byte, certCache map[string]*ecdsa.PublicKey) (*PKISecrets, error) {
key, cert, caCertPool, err := crypto.LoadAndVerifyECSecrets(keyPEM, certPEM, caPEM)
if err != nil {
return nil, fmt.Errorf("invalid certificates: %s", err)
}
p := &PKISecrets{
PrivateKeyPEM: keyPEM,
PublicKeyPEM: certPEM,
AuthorityPEM: caPEM,
CertificateCache: certCache,
privateKey: key,
publicKey: cert,
certPool: caCertPool,
}
return p, nil
}
// Type implements the interface Secrets
func (p *PKISecrets) Type() PrivateSecretsType {
return PKIType
}
// EncodingKey returns the private key
func (p *PKISecrets) EncodingKey() interface{} {
return p.privateKey
}
// PublicKey returns the public key
func (p *PKISecrets) PublicKey() interface{} {
return p.publicKey
}
// DecodingKey returns the public key
func (p *PKISecrets) DecodingKey(server string, ackCert interface{}, prevCert interface{}) (interface{}, error) {
// If we have a cache of certificates, just look there
if p.CertificateCache != nil {
cert, ok := p.CertificateCache[server]
if !ok {
return nil, fmt.Errorf("no certificate in cache for server %s", server)
}
return cert, nil
}
// If we have an inband certificate, return this one
if ackCert != nil {
return ackCert.(*x509.Certificate).PublicKey.(*ecdsa.PublicKey), nil
}
// Otherwise, return the prevCert
if prevCert != nil {
return prevCert, nil
}
return nil, errors.New("no valid certificate")
}
// VerifyPublicKey verifies if the inband public key is correct.
func (p *PKISecrets) VerifyPublicKey(pkey []byte) (interface{}, error) {
decodedCert, err := crypto.LoadAndVerifyCertificate(pkey, p.certPool)
if err != nil {
return nil, err
}
return decodedCert, nil
}
// TransmittedKey returns the PEM of the public key in the case of PKI
// if there is no certificate cache configured
func (p *PKISecrets) TransmittedKey() []byte {
return p.PublicKeyPEM
}
// AckSize returns the default size of an ACK packet
func (p *PKISecrets) AckSize() uint32 {
return uint32(336)
}
// PublicKeyAdd validates the parameter certificate.
// If valid, the corresponding key is added in the PublicKeyCache.
// If Invalid, an error is returned.
func (p *PKISecrets) PublicKeyAdd(host string, newCert []byte) error {
cert, err := crypto.LoadAndVerifyCertificate(newCert, p.certPool)
if err != nil {
return fmt.Errorf("unable to load certificate: %s", err)
}
zap.L().Debug("Adding cert for host", zap.String("host", host))
p.CertificateCache[host] = cert.PublicKey.(*ecdsa.PublicKey)
return nil
}
// AuthPEM returns the Certificate Authority PEM
func (p *PKISecrets) AuthPEM() []byte {
return p.AuthorityPEM
}
// TransmittedPEM returns the PEM certificate that is transmitted
func (p *PKISecrets) TransmittedPEM() []byte {
return p.PublicKeyPEM
}
// EncodingPEM returns the certificate PEM that is used for encoding
func (p *PKISecrets) EncodingPEM() []byte {
return p.PrivateKeyPEM
}
// PublicSecrets returns the secrets that are marshallable over the RPC interface.
func (p *PKISecrets) PublicSecrets() PublicSecrets {
return &PKIPublicSecrets{
Type: PKIType,
Key: p.PrivateKeyPEM,
Certificate: p.PublicKeyPEM,
CA: p.AuthorityPEM,
}
}
// PKIPublicSecrets includes all the secrets that can be transmitted over
// the RPC interface.
type PKIPublicSecrets struct {
Type PrivateSecretsType
Key []byte
Certificate []byte
CA []byte
}
// SecretsType returns the type of secrets.
func (p *PKIPublicSecrets) SecretsType() PrivateSecretsType {
return p.Type
}
// CertAuthority returns the cert authority
func (p *PKIPublicSecrets) CertAuthority() []byte {
return p.CA
}