mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-28 17:22:41 +00:00
Add underlining support for the PKI Enterprise SCEP work (#29604)
This commit is contained in:
@@ -62,59 +62,10 @@ var (
|
||||
endWildRegex = labelRegex + `\*`
|
||||
middleWildRegex = labelRegex + `\*` + labelRegex
|
||||
leftWildLabelRegex = regexp.MustCompile(`^(` + allWildRegex + `|` + startWildRegex + `|` + endWildRegex + `|` + middleWildRegex + `)$`)
|
||||
|
||||
// Cloned from https://github.com/golang/go/blob/82c713feb05da594567631972082af2fcba0ee4f/src/crypto/x509/x509.go#L327-L379
|
||||
oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
|
||||
oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
|
||||
oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
|
||||
oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
|
||||
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
||||
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
||||
oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
|
||||
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
||||
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
|
||||
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
||||
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
||||
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
||||
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
||||
oidSignatureEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112}
|
||||
oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29}
|
||||
|
||||
signatureAlgorithmDetails = []struct {
|
||||
algo x509.SignatureAlgorithm
|
||||
name string
|
||||
oid asn1.ObjectIdentifier
|
||||
pubKeyAlgo x509.PublicKeyAlgorithm
|
||||
hash crypto.Hash
|
||||
}{
|
||||
{x509.MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */},
|
||||
{x509.MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, x509.RSA, crypto.MD5},
|
||||
{x509.SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
|
||||
{x509.SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
|
||||
{x509.SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256},
|
||||
{x509.SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384},
|
||||
{x509.SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512},
|
||||
{x509.SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, x509.RSA, crypto.SHA256},
|
||||
{x509.SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, x509.RSA, crypto.SHA384},
|
||||
{x509.SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, x509.RSA, crypto.SHA512},
|
||||
{x509.DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1},
|
||||
{x509.DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256},
|
||||
{x509.ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1},
|
||||
{x509.ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256},
|
||||
{x509.ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384},
|
||||
{x509.ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512},
|
||||
{x509.PureEd25519, "Ed25519", oidSignatureEd25519, x509.Ed25519, crypto.Hash(0) /* no pre-hashing */},
|
||||
}
|
||||
)
|
||||
|
||||
func doesPublicKeyAlgoMatchSignatureAlgo(pubKey x509.PublicKeyAlgorithm, algo x509.SignatureAlgorithm) bool {
|
||||
for _, detail := range signatureAlgorithmDetails {
|
||||
if detail.algo == algo {
|
||||
return pubKey == detail.pubKeyAlgo
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return issuing.DoesPublicKeyAlgoMatchSignatureAlgo(pubKey, algo)
|
||||
}
|
||||
|
||||
func getFormat(data *framework.FieldData) string {
|
||||
|
||||
162
builtin/logical/pki/issuing/signing_utils.go
Normal file
162
builtin/logical/pki/issuing/signing_utils.go
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package issuing
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// DER encoded RSA PSS parameters for the
|
||||
// SHA256, SHA384, and SHA512 hashes as defined in RFC 3447, Appendix A.2.3.
|
||||
// The parameters contain the following values:
|
||||
// - hashAlgorithm contains the associated hash identifier with NULL parameters
|
||||
// - maskGenAlgorithm always contains the default mgf1SHA1 identifier
|
||||
// - saltLength contains the length of the associated hash
|
||||
// - trailerField always contains the default trailerFieldBC value
|
||||
var (
|
||||
pssParametersSHA256 = asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 162, 3, 2, 1, 32}}
|
||||
pssParametersSHA384 = asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 162, 3, 2, 1, 48}}
|
||||
pssParametersSHA512 = asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 162, 3, 2, 1, 64}}
|
||||
)
|
||||
|
||||
var (
|
||||
emptyRawValue = asn1.RawValue{}
|
||||
|
||||
oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
|
||||
oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
|
||||
oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
|
||||
oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
|
||||
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
||||
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
||||
oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
|
||||
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
||||
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
|
||||
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
||||
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
||||
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
||||
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
||||
oidSignatureEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112}
|
||||
oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29}
|
||||
|
||||
signatureAlgorithmDetails = []struct {
|
||||
algo x509.SignatureAlgorithm
|
||||
name string
|
||||
oid asn1.ObjectIdentifier
|
||||
params asn1.RawValue
|
||||
pubKeyAlgo x509.PublicKeyAlgorithm
|
||||
hash crypto.Hash
|
||||
isRSAPSS bool
|
||||
}{
|
||||
{x509.MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, asn1.NullRawValue, x509.RSA, crypto.MD5, false},
|
||||
{x509.SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, asn1.NullRawValue, x509.RSA, crypto.SHA1, false},
|
||||
{x509.SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, asn1.NullRawValue, x509.RSA, crypto.SHA1, false},
|
||||
{x509.SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, asn1.NullRawValue, x509.RSA, crypto.SHA256, false},
|
||||
{x509.SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, asn1.NullRawValue, x509.RSA, crypto.SHA384, false},
|
||||
{x509.SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, asn1.NullRawValue, x509.RSA, crypto.SHA512, false},
|
||||
{x509.SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, pssParametersSHA256, x509.RSA, crypto.SHA256, true},
|
||||
{x509.SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, pssParametersSHA384, x509.RSA, crypto.SHA384, true},
|
||||
{x509.SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, pssParametersSHA512, x509.RSA, crypto.SHA512, true},
|
||||
{x509.DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, emptyRawValue, x509.DSA, crypto.SHA1, false},
|
||||
{x509.DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, emptyRawValue, x509.DSA, crypto.SHA256, false},
|
||||
{x509.ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, emptyRawValue, x509.ECDSA, crypto.SHA1, false},
|
||||
{x509.ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, emptyRawValue, x509.ECDSA, crypto.SHA256, false},
|
||||
{x509.ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, emptyRawValue, x509.ECDSA, crypto.SHA384, false},
|
||||
{x509.ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, emptyRawValue, x509.ECDSA, crypto.SHA512, false},
|
||||
{x509.PureEd25519, "Ed25519", oidSignatureEd25519, emptyRawValue, x509.Ed25519, crypto.Hash(0) /* no pre-hashing */, false},
|
||||
}
|
||||
)
|
||||
|
||||
// SigningParamsForKey returns the signature algorithm and its Algorithm
|
||||
// Identifier to use for signing, based on the key type. If sigAlgo is not zero
|
||||
// then it overrides the default.
|
||||
// This function is copied from crypto/x509/x509.go in the Go standard library.
|
||||
func SigningParamsForKey(key crypto.Signer, sigAlgo x509.SignatureAlgorithm) (x509.SignatureAlgorithm, pkix.AlgorithmIdentifier, error) {
|
||||
var ai pkix.AlgorithmIdentifier
|
||||
var pubType x509.PublicKeyAlgorithm
|
||||
var defaultAlgo x509.SignatureAlgorithm
|
||||
|
||||
switch pub := key.Public().(type) {
|
||||
case *rsa.PublicKey:
|
||||
pubType = x509.RSA
|
||||
defaultAlgo = x509.SHA256WithRSA
|
||||
|
||||
case *ecdsa.PublicKey:
|
||||
pubType = x509.ECDSA
|
||||
switch pub.Curve {
|
||||
case elliptic.P224(), elliptic.P256():
|
||||
defaultAlgo = x509.ECDSAWithSHA256
|
||||
case elliptic.P384():
|
||||
defaultAlgo = x509.ECDSAWithSHA384
|
||||
case elliptic.P521():
|
||||
defaultAlgo = x509.ECDSAWithSHA512
|
||||
default:
|
||||
return 0, ai, errors.New("x509: unsupported elliptic curve")
|
||||
}
|
||||
|
||||
case ed25519.PublicKey:
|
||||
pubType = x509.Ed25519
|
||||
defaultAlgo = x509.PureEd25519
|
||||
|
||||
default:
|
||||
return 0, ai, errors.New("x509: only RSA, ECDSA and Ed25519 keys supported")
|
||||
}
|
||||
|
||||
if sigAlgo == 0 {
|
||||
sigAlgo = defaultAlgo
|
||||
}
|
||||
|
||||
for _, details := range signatureAlgorithmDetails {
|
||||
if details.algo == sigAlgo {
|
||||
if details.pubKeyAlgo != pubType {
|
||||
return 0, ai, errors.New("x509: requested SignatureAlgorithm does not match private key type")
|
||||
}
|
||||
if details.hash == crypto.MD5 {
|
||||
return 0, ai, errors.New("x509: signing with MD5 is not supported")
|
||||
}
|
||||
|
||||
return sigAlgo, pkix.AlgorithmIdentifier{
|
||||
Algorithm: details.oid,
|
||||
Parameters: details.params,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, ai, errors.New("x509: unknown SignatureAlgorithm")
|
||||
}
|
||||
|
||||
func DoesPublicKeyAlgoMatchSignatureAlgo(pubKey x509.PublicKeyAlgorithm, algo x509.SignatureAlgorithm) bool {
|
||||
for _, detail := range signatureAlgorithmDetails {
|
||||
if detail.algo == algo {
|
||||
return pubKey == detail.pubKeyAlgo
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsRSAPSS(algo x509.SignatureAlgorithm) bool {
|
||||
for _, details := range signatureAlgorithmDetails {
|
||||
if details.algo == algo {
|
||||
return details.isRSAPSS
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func HashFunc(algo x509.SignatureAlgorithm) crypto.Hash {
|
||||
for _, details := range signatureAlgorithmDetails {
|
||||
if details.algo == algo {
|
||||
return details.hash
|
||||
}
|
||||
}
|
||||
return crypto.Hash(0)
|
||||
}
|
||||
18
builtin/logical/pki/parsing/asn1.go
Normal file
18
builtin/logical/pki/parsing/asn1.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package parsing
|
||||
|
||||
import "encoding/asn1"
|
||||
|
||||
// Asn1UnmarshallNoTrailing is a wrapper around asn1.Unmarshal that ensures there
|
||||
// is no trailing data in the input returning an error if there is.
|
||||
func Asn1UnmarshallNoTrailing(b []byte, val any) error {
|
||||
rest, err := asn1.Unmarshal(b, val)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(rest) != 0 {
|
||||
return asn1.SyntaxError{Msg: "trailing data"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
52
builtin/logical/pki/parsing/asn1_test.go
Normal file
52
builtin/logical/pki/parsing/asn1_test.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package parsing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestAsn1UnmarshallNoTrailing tests the Asn1UnmarshallNoTrailing function returns
|
||||
// errors as we expect if the input is not marshalled correctly or there is trailing
|
||||
// data.
|
||||
func TestAsn1UnmarshallNoTrailing(t *testing.T) {
|
||||
stringToMarshal := "a string"
|
||||
marshal, err := asn1.Marshal(stringToMarshal)
|
||||
require.NoError(t, err, "marshal failed")
|
||||
|
||||
var myTestString string
|
||||
|
||||
type args struct {
|
||||
b []byte
|
||||
val any
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"happy-path", args{marshal, &myTestString}, false},
|
||||
{"bad-marshalling", args{[]byte("incorrect"), &myTestString}, true},
|
||||
{"trailing-data", args{append(marshal, []byte("\n")...), &myTestString}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
myTestString = ""
|
||||
err := Asn1UnmarshallNoTrailing(tt.args.b, tt.args.val)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Asn1UnmarshallNoTrailing() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
if !tt.wantErr {
|
||||
if myTestString != stringToMarshal {
|
||||
t.Errorf("Asn1UnmarshallNoTrailing() = %v, want %v", myTestString, stringToMarshal)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -52,15 +52,40 @@ func (p7 *PKCS7) DecryptUsingPSK(key []byte) ([]byte, error) {
|
||||
return data.EncryptedContentInfo.decrypt(key)
|
||||
}
|
||||
|
||||
func (p7 *PKCS7) GetEncryptionAlgo() (int, error) {
|
||||
data, ok := p7.raw.(envelopedData)
|
||||
if !ok {
|
||||
return -1, ErrNotEncryptedContent
|
||||
}
|
||||
|
||||
alg := data.EncryptedContentInfo.ContentEncryptionAlgorithm.Algorithm
|
||||
return encryptedAlgoOidToConstant(alg)
|
||||
}
|
||||
|
||||
// convert the Encrypted Algorithm OID to our internal constants for Encryption Algorithms
|
||||
func encryptedAlgoOidToConstant(alg asn1.ObjectIdentifier) (int, error) {
|
||||
switch {
|
||||
case alg.Equal(OIDEncryptionAlgorithmDESCBC):
|
||||
return EncryptionAlgorithmDESCBC, nil
|
||||
case alg.Equal(OIDEncryptionAlgorithmDESEDE3CBC):
|
||||
return EncryptionAlgorithmDESEDE3CBC, nil
|
||||
case alg.Equal(OIDEncryptionAlgorithmAES128CBC):
|
||||
return EncryptionAlgorithmAES128CBC, nil
|
||||
case alg.Equal(OIDEncryptionAlgorithmAES256CBC):
|
||||
return EncryptionAlgorithmAES256CBC, nil
|
||||
case alg.Equal(OIDEncryptionAlgorithmAES128GCM):
|
||||
return EncryptionAlgorithmAES128GCM, nil
|
||||
case alg.Equal(OIDEncryptionAlgorithmAES256GCM):
|
||||
return EncryptionAlgorithmAES256GCM, nil
|
||||
default:
|
||||
return -1, ErrUnsupportedAlgorithm
|
||||
}
|
||||
}
|
||||
|
||||
func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
|
||||
alg := eci.ContentEncryptionAlgorithm.Algorithm
|
||||
if !alg.Equal(OIDEncryptionAlgorithmDESCBC) &&
|
||||
!alg.Equal(OIDEncryptionAlgorithmDESEDE3CBC) &&
|
||||
!alg.Equal(OIDEncryptionAlgorithmAES256CBC) &&
|
||||
!alg.Equal(OIDEncryptionAlgorithmAES128CBC) &&
|
||||
!alg.Equal(OIDEncryptionAlgorithmAES128GCM) &&
|
||||
!alg.Equal(OIDEncryptionAlgorithmAES256GCM) {
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
if _, err := encryptedAlgoOidToConstant(alg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// EncryptedContent can either be constructed of multple OCTET STRINGs
|
||||
|
||||
@@ -55,6 +55,9 @@ const (
|
||||
|
||||
// EncryptionAlgorithmAES256GCM is the AES 256 bits with GCM encryption algorithm
|
||||
EncryptionAlgorithmAES256GCM
|
||||
|
||||
// EncryptionAlgorithmDESEDE3CBC is the 3DES CBC encryption algorithm (currently only supported on decrypt)
|
||||
EncryptionAlgorithmDESEDE3CBC
|
||||
)
|
||||
|
||||
// ContentEncryptionAlgorithm determines the algorithm used to encrypt the
|
||||
@@ -77,10 +80,10 @@ type aesGCMParameters struct {
|
||||
ICVLen int
|
||||
}
|
||||
|
||||
func encryptAESGCM(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
|
||||
func encryptAESGCM(content []byte, key []byte, algo int) ([]byte, *encryptedContentInfo, error) {
|
||||
var keyLen int
|
||||
var algID asn1.ObjectIdentifier
|
||||
switch ContentEncryptionAlgorithm {
|
||||
switch algo {
|
||||
case EncryptionAlgorithmAES128GCM:
|
||||
keyLen = 16
|
||||
algID = OIDEncryptionAlgorithmAES128GCM
|
||||
@@ -88,7 +91,7 @@ func encryptAESGCM(content []byte, key []byte) ([]byte, *encryptedContentInfo, e
|
||||
keyLen = 32
|
||||
algID = OIDEncryptionAlgorithmAES256GCM
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESGCM: %d", ContentEncryptionAlgorithm)
|
||||
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESGCM: %d", algo)
|
||||
}
|
||||
if key == nil {
|
||||
// Create AES key
|
||||
@@ -147,10 +150,23 @@ func encryptAESGCM(content []byte, key []byte) ([]byte, *encryptedContentInfo, e
|
||||
return key, &eci, nil
|
||||
}
|
||||
|
||||
func encryptDESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
|
||||
func encryptDESCBC(content []byte, key []byte, algo int) ([]byte, *encryptedContentInfo, error) {
|
||||
var keyLen int
|
||||
var algID asn1.ObjectIdentifier
|
||||
switch algo {
|
||||
case EncryptionAlgorithmDESCBC:
|
||||
keyLen = 8
|
||||
algID = OIDEncryptionAlgorithmDESCBC
|
||||
case EncryptionAlgorithmDESEDE3CBC:
|
||||
keyLen = 24
|
||||
algID = OIDEncryptionAlgorithmDESEDE3CBC
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptDESCBC: %d", algo)
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
// Create DES key
|
||||
key = make([]byte, 8)
|
||||
// Create our key
|
||||
key = make([]byte, keyLen)
|
||||
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
@@ -166,9 +182,20 @@ func encryptDESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, e
|
||||
}
|
||||
|
||||
// Encrypt padded content
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
var block cipher.Block
|
||||
switch algo {
|
||||
case EncryptionAlgorithmDESCBC:
|
||||
block, err = des.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
case EncryptionAlgorithmDESEDE3CBC:
|
||||
block, err = des.NewTripleDESCipher(key)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptDESCBC: %d", algo)
|
||||
}
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
plaintext, err := pad(content, mode.BlockSize())
|
||||
@@ -182,7 +209,7 @@ func encryptDESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, e
|
||||
eci := encryptedContentInfo{
|
||||
ContentType: OIDData,
|
||||
ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
||||
Algorithm: OIDEncryptionAlgorithmDESCBC,
|
||||
Algorithm: algID,
|
||||
Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
|
||||
},
|
||||
EncryptedContent: marshalEncryptedContent(cyphertext),
|
||||
@@ -191,10 +218,10 @@ func encryptDESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, e
|
||||
return key, &eci, nil
|
||||
}
|
||||
|
||||
func encryptAESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
|
||||
func encryptAESCBC(content []byte, key []byte, algo int) ([]byte, *encryptedContentInfo, error) {
|
||||
var keyLen int
|
||||
var algID asn1.ObjectIdentifier
|
||||
switch ContentEncryptionAlgorithm {
|
||||
switch algo {
|
||||
case EncryptionAlgorithmAES128CBC:
|
||||
keyLen = 16
|
||||
algID = OIDEncryptionAlgorithmAES128CBC
|
||||
@@ -202,7 +229,7 @@ func encryptAESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, e
|
||||
keyLen = 32
|
||||
algID = OIDEncryptionAlgorithmAES256CBC
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESCBC: %d", ContentEncryptionAlgorithm)
|
||||
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESCBC: %d", algo)
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
@@ -260,22 +287,38 @@ func encryptAESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, e
|
||||
//
|
||||
// TODO(fullsailor): Add support for encrypting content with other algorithms
|
||||
func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) {
|
||||
return EncryptWithAlgo(content, recipients, ContentEncryptionAlgorithm)
|
||||
}
|
||||
|
||||
// EncryptWithAlgo creates and returns an envelope data PKCS7 structure with encrypted
|
||||
// recipient keys for each recipient public key using the specified algorithm.
|
||||
//
|
||||
// The algorithm must be one of the supported encryption algorithms:
|
||||
// - EncryptionAlgorithmDESCBC
|
||||
// - EncryptionAlgorithmDESEDE3CBC
|
||||
// - EncryptionAlgorithmAES128CBC
|
||||
// - EncryptionAlgorithmAES256CBC
|
||||
// - EncryptionAlgorithmAES128GCM
|
||||
// - EncryptionAlgorithmAES256GCM
|
||||
func EncryptWithAlgo(content []byte, recipients []*x509.Certificate, algo int) ([]byte, error) {
|
||||
var eci *encryptedContentInfo
|
||||
var key []byte
|
||||
var err error
|
||||
|
||||
// Apply chosen symmetric encryption method
|
||||
switch ContentEncryptionAlgorithm {
|
||||
switch algo {
|
||||
case EncryptionAlgorithmDESCBC:
|
||||
key, eci, err = encryptDESCBC(content, nil)
|
||||
fallthrough
|
||||
case EncryptionAlgorithmDESEDE3CBC:
|
||||
key, eci, err = encryptDESCBC(content, nil, algo)
|
||||
case EncryptionAlgorithmAES128CBC:
|
||||
fallthrough
|
||||
case EncryptionAlgorithmAES256CBC:
|
||||
key, eci, err = encryptAESCBC(content, nil)
|
||||
key, eci, err = encryptAESCBC(content, nil, algo)
|
||||
case EncryptionAlgorithmAES128GCM:
|
||||
fallthrough
|
||||
case EncryptionAlgorithmAES256GCM:
|
||||
key, eci, err = encryptAESGCM(content, nil)
|
||||
key, eci, err = encryptAESGCM(content, nil, algo)
|
||||
|
||||
default:
|
||||
return nil, ErrUnsupportedEncryptionAlgorithm
|
||||
@@ -330,6 +373,18 @@ func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) {
|
||||
// EncryptUsingPSK creates and returns an encrypted data PKCS7 structure,
|
||||
// encrypted using caller provided pre-shared secret.
|
||||
func EncryptUsingPSK(content []byte, key []byte) ([]byte, error) {
|
||||
return EncryptUsingPSKWithAlgo(content, key, ContentEncryptionAlgorithm)
|
||||
}
|
||||
|
||||
// EncryptUsingPSKWithAlgo creates and returns an encrypted data PKCS7 structure,
|
||||
// encrypted using caller provided pre-shared secret with the specified algorithm.
|
||||
//
|
||||
// The algorithm must be one of the supported encryption algorithms:
|
||||
// - EncryptionAlgorithmDESCBC
|
||||
// - EncryptionAlgorithmDESEDE3CBC
|
||||
// - EncryptionAlgorithmAES128GCM
|
||||
// - EncryptionAlgorithmAES256GCM
|
||||
func EncryptUsingPSKWithAlgo(content []byte, key []byte, algo int) ([]byte, error) {
|
||||
var eci *encryptedContentInfo
|
||||
var err error
|
||||
|
||||
@@ -338,14 +393,16 @@ func EncryptUsingPSK(content []byte, key []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Apply chosen symmetric encryption method
|
||||
switch ContentEncryptionAlgorithm {
|
||||
switch algo {
|
||||
case EncryptionAlgorithmDESCBC:
|
||||
_, eci, err = encryptDESCBC(content, key)
|
||||
fallthrough
|
||||
case EncryptionAlgorithmDESEDE3CBC:
|
||||
_, eci, err = encryptDESCBC(content, key, algo)
|
||||
|
||||
case EncryptionAlgorithmAES128GCM:
|
||||
fallthrough
|
||||
case EncryptionAlgorithmAES256GCM:
|
||||
_, eci, err = encryptAESGCM(content, key)
|
||||
_, eci, err = encryptAESGCM(content, key, algo)
|
||||
|
||||
default:
|
||||
return nil, ErrUnsupportedEncryptionAlgorithm
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
func TestEncrypt(t *testing.T) {
|
||||
modes := []int{
|
||||
EncryptionAlgorithmDESCBC,
|
||||
EncryptionAlgorithmDESEDE3CBC,
|
||||
EncryptionAlgorithmAES128CBC,
|
||||
EncryptionAlgorithmAES256CBC,
|
||||
EncryptionAlgorithmAES128GCM,
|
||||
@@ -49,7 +50,9 @@ func TestEncrypt(t *testing.T) {
|
||||
func TestEncryptUsingPSK(t *testing.T) {
|
||||
modes := []int{
|
||||
EncryptionAlgorithmDESCBC,
|
||||
EncryptionAlgorithmDESEDE3CBC,
|
||||
EncryptionAlgorithmAES128GCM,
|
||||
EncryptionAlgorithmAES256GCM,
|
||||
}
|
||||
|
||||
for _, mode := range modes {
|
||||
@@ -60,9 +63,16 @@ func TestEncryptUsingPSK(t *testing.T) {
|
||||
switch mode {
|
||||
case EncryptionAlgorithmDESCBC:
|
||||
key = []byte("64BitKey")
|
||||
case EncryptionAlgorithmDESEDE3CBC:
|
||||
key = []byte("192BitKeyForMoreSecurity")
|
||||
case EncryptionAlgorithmAES128GCM:
|
||||
key = []byte("128BitKey4AESGCM")
|
||||
case EncryptionAlgorithmAES256GCM:
|
||||
key = []byte("256BitKey4AESGCM256BitKey4AESGCM")
|
||||
default:
|
||||
t.Errorf("unsupported mode %d", mode)
|
||||
}
|
||||
|
||||
ciphertext, err := EncryptUsingPSK(plaintext, key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -81,6 +81,10 @@ var (
|
||||
OIDEncryptionAlgorithmAES256GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 46}
|
||||
)
|
||||
|
||||
func GetHashForDigestAlgorithm(digestAlg asn1.ObjectIdentifier) (crypto.Hash, error) {
|
||||
return getHashForOID(digestAlg)
|
||||
}
|
||||
|
||||
func getHashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error) {
|
||||
switch {
|
||||
case oid.Equal(OIDDigestAlgorithmSHA1), oid.Equal(OIDDigestAlgorithmECDSASHA1),
|
||||
|
||||
Reference in New Issue
Block a user