Skip to content

Commit 977d131

Browse files
Disable encrypted private key support when in FIPS mode (#278)
1 parent 1aa0d48 commit 977d131

File tree

3 files changed

+112
-51
lines changed

3 files changed

+112
-51
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//go:build requirefips
19+
20+
package tlscommon
21+
22+
import (
23+
"encoding/pem"
24+
"errors"
25+
"fmt"
26+
)
27+
28+
func decryptPKCS1Key(block pem.Block, passphrase []byte) (pem.Block, error) {
29+
return block, fmt.Errorf("encrypted private keys are unsupported in FIPS mode: %w", errors.ErrUnsupported)
30+
}
31+
func decryptPKCS8Key(block pem.Block, passphrase []byte) (pem.Block, error) {
32+
return block, fmt.Errorf("encrypted private keys are unsupported in FIPS mode: %w", errors.ErrUnsupported)
33+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//go:build !requirefips
19+
20+
package tlscommon
21+
22+
import (
23+
"crypto/ecdsa"
24+
"crypto/rsa"
25+
"crypto/x509"
26+
"encoding/pem"
27+
"errors"
28+
"fmt"
29+
30+
"github.com/elastic/pkcs8"
31+
)
32+
33+
func decryptPKCS1Key(block pem.Block, passphrase []byte) (pem.Block, error) {
34+
if len(passphrase) == 0 {
35+
return block, errors.New("no passphrase available")
36+
}
37+
38+
// Note, decrypting pem might succeed even with wrong password, but
39+
// only noise will be stored in buffer in this case.
40+
buffer, err := x509.DecryptPEMBlock(&block, passphrase) //nolint: staticcheck // deprecated, we have to get rid of it
41+
if err != nil {
42+
return block, fmt.Errorf("failed to decrypt pem: %w", err)
43+
}
44+
45+
// DEK-Info contains encryption info. Remove header to mark block as
46+
// unencrypted.
47+
delete(block.Headers, "DEK-Info")
48+
block.Bytes = buffer
49+
50+
return block, nil
51+
}
52+
53+
func decryptPKCS8Key(block pem.Block, passphrase []byte) (pem.Block, error) {
54+
if len(passphrase) == 0 {
55+
return block, errors.New("no passphrase available")
56+
}
57+
58+
key, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes, passphrase)
59+
if err != nil {
60+
return block, fmt.Errorf("failed to parse key: %w", err)
61+
}
62+
63+
switch key.(type) {
64+
case *rsa.PrivateKey:
65+
block.Type = "RSA PRIVATE KEY"
66+
case *ecdsa.PrivateKey:
67+
block.Type = "ECDSA PRIVATE KEY"
68+
default:
69+
return block, fmt.Errorf("unknown key type %T", key)
70+
}
71+
72+
buffer, err := x509.MarshalPKCS8PrivateKey(key)
73+
if err != nil {
74+
return block, fmt.Errorf("failed to marshal decrypted private key: %w", err)
75+
}
76+
block.Bytes = buffer
77+
78+
return block, nil
79+
}

transport/tlscommon/tls.go

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ package tlscommon
1919

2020
import (
2121
"bytes"
22-
"crypto/ecdsa"
23-
"crypto/rsa"
2422
"crypto/tls"
2523
"crypto/x509"
2624
"encoding/pem"
@@ -31,7 +29,6 @@ import (
3129
"strings"
3230

3331
"github.com/elastic/elastic-agent-libs/logp"
34-
"github.com/elastic/pkcs8"
3532
)
3633

3734
const logSelector = "tls"
@@ -150,54 +147,6 @@ func ReadPEMFile(log *logp.Logger, s, passphrase string) ([]byte, error) {
150147
return buffer.Bytes(), nil
151148
}
152149

153-
func decryptPKCS1Key(block pem.Block, passphrase []byte) (pem.Block, error) {
154-
if len(passphrase) == 0 {
155-
return block, errors.New("no passphrase available")
156-
}
157-
158-
// Note, decrypting pem might succeed even with wrong password, but
159-
// only noise will be stored in buffer in this case.
160-
buffer, err := x509.DecryptPEMBlock(&block, passphrase) //nolint: staticcheck // deprecated, we have to get rid of it
161-
if err != nil {
162-
return block, fmt.Errorf("failed to decrypt pem: %w", err)
163-
}
164-
165-
// DEK-Info contains encryption info. Remove header to mark block as
166-
// unencrypted.
167-
delete(block.Headers, "DEK-Info")
168-
block.Bytes = buffer
169-
170-
return block, nil
171-
}
172-
173-
func decryptPKCS8Key(block pem.Block, passphrase []byte) (pem.Block, error) {
174-
if len(passphrase) == 0 {
175-
return block, errors.New("no passphrase available")
176-
}
177-
178-
key, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes, passphrase)
179-
if err != nil {
180-
return block, fmt.Errorf("failed to parse key: %w", err)
181-
}
182-
183-
switch key.(type) {
184-
case *rsa.PrivateKey:
185-
block.Type = "RSA PRIVATE KEY"
186-
case *ecdsa.PrivateKey:
187-
block.Type = "ECDSA PRIVATE KEY"
188-
default:
189-
return block, fmt.Errorf("unknown key type %T", key)
190-
}
191-
192-
buffer, err := x509.MarshalPKCS8PrivateKey(key)
193-
if err != nil {
194-
return block, fmt.Errorf("failed to marshal decrypted private key: %w", err)
195-
}
196-
block.Bytes = buffer
197-
198-
return block, nil
199-
}
200-
201150
// LoadCertificateAuthorities read the slice of CAcert and return a Certpool.
202151
func LoadCertificateAuthorities(CAs []string) (*x509.CertPool, []error) {
203152
errors := []error{}

0 commit comments

Comments
 (0)