-
Notifications
You must be signed in to change notification settings - Fork 7
/
tpmkey.go
184 lines (175 loc) · 5.66 KB
/
tpmkey.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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package attestedtls
import (
"context"
"crypto"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"io"
log "github.com/sirupsen/logrus"
// local modules
ci "github.com/Fraunhofer-AISEC/cmc/cmcinterface"
// debug
"encoding/hex"
)
func convertHash(opts crypto.SignerOpts) (ci.HashFunction, error) {
switch opts.HashFunc() {
case crypto.MD4:
return ci.HashFunction_MD4, nil
case crypto.MD5:
return ci.HashFunction_MD5, nil
case crypto.SHA1:
return ci.HashFunction_SHA1, nil
case crypto.SHA224:
return ci.HashFunction_SHA224, nil
case crypto.SHA256:
return ci.HashFunction_SHA256, nil
case crypto.SHA384:
return ci.HashFunction_SHA384, nil
case crypto.SHA512:
return ci.HashFunction_SHA512, nil
case crypto.MD5SHA1:
return ci.HashFunction_MD5SHA1, nil
case crypto.RIPEMD160:
return ci.HashFunction_RIPEMD160, nil
case crypto.SHA3_224:
return ci.HashFunction_SHA3_224, nil
case crypto.SHA3_256:
return ci.HashFunction_SHA3_256, nil
case crypto.SHA3_384:
return ci.HashFunction_SHA3_384, nil
case crypto.SHA3_512:
return ci.HashFunction_SHA3_512, nil
case crypto.SHA512_224:
return ci.HashFunction_SHA512_224, nil
case crypto.SHA512_256:
return ci.HashFunction_SHA512_256, nil
case crypto.BLAKE2s_256:
return ci.HashFunction_BLAKE2s_256, nil
case crypto.BLAKE2b_256:
return ci.HashFunction_BLAKE2b_256, nil
case crypto.BLAKE2b_384:
return ci.HashFunction_BLAKE2b_384, nil
case crypto.BLAKE2b_512:
return ci.HashFunction_BLAKE2b_512, nil
default:
}
return ci.HashFunction_SHA512, errors.New("[PrivateKey] Could not determine correct Hash function")
}
/***********************************************************
* PrivateKey Wrapper Implementing crypto.Signer interface
* Contacts cmcd for signing operations */
type PrivateKey struct {
pubKey crypto.PublicKey
}
/* Implementation of Sign() in crypto.Signer iface
* Contacts cmcd for sign operation */
func (priv PrivateKey) Sign(random io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
var req ci.TLSSignRequest
var resp *ci.TLSSignResponse
var hash ci.HashFunction
var err error
// Get backend connection
cmcClient, conn, cancel := getCMCServiceConn()
if cmcClient == nil {
return nil, errors.New("[PrivateKey] Connection failed. No signing performed")
}
defer conn.Close()
defer cancel()
log.Trace("[PrivateKey] Contacting backend for Sign Operation")
// Create Sign request
hash, err = convertHash(opts)
if err != nil {
log.Error(err)
return nil, errors.New("[Private Key] Sign request creation failed")
}
req = ci.TLSSignRequest{
Id: id,
Content: digest,
Hashtype: hash,
}
// parse additional signing options - not implemented fields assume recommend defaults
if pssOpts, ok := opts.(*rsa.PSSOptions); ok {
req.PssOpts = &ci.PSSOptions{SaltLength: int32(pssOpts.SaltLength)}
}
// Send Sign request
resp, err = cmcClient.TLSSign(context.Background(), &req)
if err != nil {
log.Error(err)
return nil, errors.New("[PrivateKey] Sign request failed")
}
// Check Sign response
if resp.GetStatus() != ci.Status_OK {
return nil, errors.New("[PrivateKey] Signature creation failed")
}
log.Info("[PrivateKey] returning signed content of size ", len(resp.GetSignedContent()))
log.Trace("[PrivateKey] signature: \n ", hex.EncodeToString(resp.GetSignedContent()))
return resp.GetSignedContent(), nil
}
func (priv PrivateKey) Public() crypto.PublicKey {
return priv.pubKey
}
/***********************************************************
* Public function
*/
func GetCert() (tls.Certificate, error) {
var err error
var req ci.TLSCertRequest
var resp *ci.TLSCertResponse
var x509Cert *x509.Certificate
// return
var tlsCert tls.Certificate
// Get backend connection
cmcClient, cmcconn, cancel := getCMCServiceConn()
if cmcClient == nil {
return tls.Certificate{}, errors.New("[Listener] Connection failed. No Cert obtained")
}
defer cmcconn.Close()
defer cancel()
// Create TLSCert request
req = ci.TLSCertRequest{
Id: id,
}
// Call TLSCert request
resp, err = cmcClient.TLSCert(context.Background(), &req)
if err != nil {
log.Error(err)
return tls.Certificate{}, errors.New("[Listener] Failed to request TLS certificate")
}
// Check TLSCert response
if resp.GetStatus() != ci.Status_OK || len(resp.GetCertificate()) == 0 {
return tls.Certificate{}, errors.New("[Listener] Could not receive TLS certificate")
}
// Convert each certificate (assuming it has superfluous "---------[]BEGIN CERTIFICATE[]-----" still there)
for _, cert := range resp.GetCertificate() {
var currentBlock *pem.Block
var remain []byte
currentBlock, remain = pem.Decode(cert)
if currentBlock == nil {
return tls.Certificate{}, errors.New("[Listener] Certificate inside the certificate chain could not be decoded")
}
if newBlock, _ := pem.Decode(remain); newBlock != nil {
return tls.Certificate{}, errors.New("[Listener] Certificate inside certificate chain contain superfluous data. Expecting separate Certificates")
}
if currentBlock.Type == "CERTIFICATE" {
tlsCert.Certificate = append(tlsCert.Certificate, currentBlock.Bytes)
} else {
return tls.Certificate{}, errors.New("[Listener] Certificate inside the certificate chain not of correct type")
}
}
if len(tlsCert.Certificate) == 0 {
return tls.Certificate{}, errors.New("[Listener] Could not parse any certificate")
}
// Convert TLS cert (first cert) only to obtain its crypto.PublicKey
x509Cert, err = x509.ParseCertificate(tlsCert.Certificate[0])
if err != nil {
log.Error(err)
return tls.Certificate{}, errors.New("[Listener] Could not parse certificate")
}
// Create TLS Cert
tlsCert.PrivateKey = PrivateKey{pubKey: x509Cert.PublicKey}
// return cert
return tlsCert, nil
}