mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 04:06:18 +08:00
x509: sync with sdk #223
This commit is contained in:
parent
ed0b2551ed
commit
7c46d7b977
@ -1599,6 +1599,14 @@ var nameConstraintsTests = []nameConstraintsTest{
|
|||||||
cn: "foo.bar",
|
cn: "foo.bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// #85: .example.com is an invalid DNS name, it should not match the
|
||||||
|
// constraint example.com.
|
||||||
|
{
|
||||||
|
roots: []constraintsSpec{{ok: []string{"dns:example.com"}}},
|
||||||
|
leaf: leafSpec{sans: []string{"dns:.example.com"}},
|
||||||
|
expectedError: "cannot parse dnsName \".example.com\"",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
|
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
|
||||||
|
@ -765,6 +765,10 @@ func processExtensions(out *Certificate) error {
|
|||||||
|
|
||||||
case 35:
|
case 35:
|
||||||
// RFC 5280, 4.2.1.1
|
// RFC 5280, 4.2.1.1
|
||||||
|
if e.Critical {
|
||||||
|
// Conforming CAs MUST mark this extension as non-critical
|
||||||
|
return errors.New("x509: authority key identifier incorrectly marked critical")
|
||||||
|
}
|
||||||
val := cryptobyte.String(e.Value)
|
val := cryptobyte.String(e.Value)
|
||||||
var akid cryptobyte.String
|
var akid cryptobyte.String
|
||||||
if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
|
if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
|
||||||
@ -783,6 +787,10 @@ func processExtensions(out *Certificate) error {
|
|||||||
}
|
}
|
||||||
case 14:
|
case 14:
|
||||||
// RFC 5280, 4.2.1.2
|
// RFC 5280, 4.2.1.2
|
||||||
|
if e.Critical {
|
||||||
|
// Conforming CAs MUST mark this extension as non-critical
|
||||||
|
return errors.New("x509: subject key identifier incorrectly marked critical")
|
||||||
|
}
|
||||||
val := cryptobyte.String(e.Value)
|
val := cryptobyte.String(e.Value)
|
||||||
var skid cryptobyte.String
|
var skid cryptobyte.String
|
||||||
if !val.ReadASN1(&skid, cryptobyte_asn1.OCTET_STRING) {
|
if !val.ReadASN1(&skid, cryptobyte_asn1.OCTET_STRING) {
|
||||||
@ -800,6 +808,10 @@ func processExtensions(out *Certificate) error {
|
|||||||
}
|
}
|
||||||
} else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {
|
} else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {
|
||||||
// RFC 5280 4.2.2.1: Authority Information Access
|
// RFC 5280 4.2.2.1: Authority Information Access
|
||||||
|
if e.Critical {
|
||||||
|
// Conforming CAs MUST mark this extension as non-critical
|
||||||
|
return errors.New("x509: authority info access incorrectly marked critical")
|
||||||
|
}
|
||||||
val := cryptobyte.String(e.Value)
|
val := cryptobyte.String(e.Value)
|
||||||
if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) {
|
if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) {
|
||||||
return errors.New("x509: invalid authority info access")
|
return errors.New("x509: invalid authority info access")
|
||||||
|
@ -256,6 +256,11 @@ func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {
|
|||||||
} else {
|
} else {
|
||||||
reverseLabels = append(reverseLabels, domain[i+1:])
|
reverseLabels = append(reverseLabels, domain[i+1:])
|
||||||
domain = domain[:i]
|
domain = domain[:i]
|
||||||
|
if i == 0 { // domain == ""
|
||||||
|
// domain is prefixed with an empty label, append an empty
|
||||||
|
// string to reverseLabels to indicate this.
|
||||||
|
reverseLabels = append(reverseLabels, "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,6 +865,11 @@ func validHostname(host string, isPattern bool) bool {
|
|||||||
if len(host) == 0 {
|
if len(host) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if host == "*" {
|
||||||
|
// Bare wildcards are not allowed, they are not valid DNS names,
|
||||||
|
// nor are they allowed per RFC 6125.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for i, part := range strings.Split(host, ".") {
|
for i, part := range strings.Split(host, ".") {
|
||||||
if part == "" {
|
if part == "" {
|
||||||
|
@ -2783,3 +2783,29 @@ func TestVerifyNilPubKey(t *testing.T) {
|
|||||||
t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{})
|
t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVerifyBareWildcard(t *testing.T) {
|
||||||
|
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to generate key: %s", err)
|
||||||
|
}
|
||||||
|
tmpl := &Certificate{
|
||||||
|
SerialNumber: big.NewInt(1),
|
||||||
|
Subject: pkix.Name{CommonName: "test"},
|
||||||
|
NotBefore: time.Now().Add(-time.Hour),
|
||||||
|
NotAfter: time.Now().Add(time.Hour),
|
||||||
|
DNSNames: []string{"*"},
|
||||||
|
}
|
||||||
|
cDER, err := CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create certificate: %s", err)
|
||||||
|
}
|
||||||
|
c, err := ParseCertificate(cDER)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse certificate: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.VerifyHostname("label"); err == nil {
|
||||||
|
t.Fatalf("VerifyHostname unexpected success with bare wildcard SAN")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
447
smx509/x509.go
447
smx509/x509.go
@ -211,15 +211,15 @@ type SignatureAlgorithm = x509.SignatureAlgorithm
|
|||||||
const (
|
const (
|
||||||
UnknownSignatureAlgorithm = x509.UnknownSignatureAlgorithm
|
UnknownSignatureAlgorithm = x509.UnknownSignatureAlgorithm
|
||||||
|
|
||||||
MD2WithRSA = x509.MD2WithRSA
|
MD2WithRSA = x509.MD2WithRSA // Unsupported.
|
||||||
MD5WithRSA = x509.MD5WithRSA // Only supported for signing, not verification.
|
MD5WithRSA = x509.MD5WithRSA // Only supported for signing, not verification.
|
||||||
SHA1WithRSA = x509.SHA1WithRSA
|
SHA1WithRSA = x509.SHA1WithRSA // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses.
|
||||||
SHA256WithRSA = x509.SHA256WithRSA
|
SHA256WithRSA = x509.SHA256WithRSA
|
||||||
SHA384WithRSA = x509.SHA384WithRSA
|
SHA384WithRSA = x509.SHA384WithRSA
|
||||||
SHA512WithRSA = x509.SHA512WithRSA
|
SHA512WithRSA = x509.SHA512WithRSA
|
||||||
DSAWithSHA1 = x509.DSAWithSHA1 // Unsupported.
|
DSAWithSHA1 = x509.DSAWithSHA1 // Unsupported.
|
||||||
DSAWithSHA256 = x509.DSAWithSHA256 // Unsupported.
|
DSAWithSHA256 = x509.DSAWithSHA256 // Unsupported.
|
||||||
ECDSAWithSHA1 = x509.ECDSAWithSHA1
|
ECDSAWithSHA1 = x509.ECDSAWithSHA1 // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses.
|
||||||
ECDSAWithSHA256 = x509.ECDSAWithSHA256
|
ECDSAWithSHA256 = x509.ECDSAWithSHA256
|
||||||
ECDSAWithSHA384 = x509.ECDSAWithSHA384
|
ECDSAWithSHA384 = x509.ECDSAWithSHA384
|
||||||
ECDSAWithSHA512 = x509.ECDSAWithSHA512
|
ECDSAWithSHA512 = x509.ECDSAWithSHA512
|
||||||
@ -228,16 +228,25 @@ const (
|
|||||||
SHA512WithRSAPSS = x509.SHA512WithRSAPSS
|
SHA512WithRSAPSS = x509.SHA512WithRSAPSS
|
||||||
PureEd25519 = x509.PureEd25519
|
PureEd25519 = x509.PureEd25519
|
||||||
|
|
||||||
SM2WithSM3 SignatureAlgorithm = 99
|
SM2WithSM3 SignatureAlgorithm = 99 // Make sure the vaule is not conflict with x509.SignatureAlgorithm
|
||||||
)
|
)
|
||||||
|
|
||||||
func isRSAPSS(algo SignatureAlgorithm) bool {
|
func isRSAPSS(algo SignatureAlgorithm) bool {
|
||||||
switch algo {
|
for _, details := range signatureAlgorithmDetails {
|
||||||
case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS:
|
if details.algo == algo {
|
||||||
return true
|
return details.isRSAPSS
|
||||||
default:
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func hashFunc(algo SignatureAlgorithm) crypto.Hash {
|
||||||
|
for _, details := range signatureAlgorithmDetails {
|
||||||
|
if details.algo == algo {
|
||||||
|
return details.hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crypto.Hash(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PublicKeyAlgorithm = x509.PublicKeyAlgorithm
|
type PublicKeyAlgorithm = x509.PublicKeyAlgorithm
|
||||||
@ -341,41 +350,45 @@ var signatureAlgorithmDetails = []struct {
|
|||||||
algo SignatureAlgorithm
|
algo SignatureAlgorithm
|
||||||
name string
|
name string
|
||||||
oid asn1.ObjectIdentifier
|
oid asn1.ObjectIdentifier
|
||||||
|
params asn1.RawValue
|
||||||
pubKeyAlgo PublicKeyAlgorithm
|
pubKeyAlgo PublicKeyAlgorithm
|
||||||
hash crypto.Hash
|
hash crypto.Hash
|
||||||
|
isRSAPSS bool
|
||||||
}{
|
}{
|
||||||
{MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */},
|
{MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, asn1.NullRawValue, RSA, crypto.Hash(0) /* no value for MD2 */, false},
|
||||||
{MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, RSA, crypto.MD5},
|
{MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, asn1.NullRawValue, RSA, crypto.MD5, false},
|
||||||
{SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, RSA, crypto.SHA1},
|
{SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, asn1.NullRawValue, RSA, crypto.SHA1, false},
|
||||||
{SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, RSA, crypto.SHA1},
|
{SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, asn1.NullRawValue, RSA, crypto.SHA1, false},
|
||||||
{SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, RSA, crypto.SHA256},
|
{SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, asn1.NullRawValue, RSA, crypto.SHA256, false},
|
||||||
{SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, RSA, crypto.SHA384},
|
{SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, asn1.NullRawValue, RSA, crypto.SHA384, false},
|
||||||
{SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, RSA, crypto.SHA512},
|
{SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, asn1.NullRawValue, RSA, crypto.SHA512, false},
|
||||||
{SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA256},
|
{SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, pssParametersSHA256, RSA, crypto.SHA256, true},
|
||||||
{SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA384},
|
{SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, pssParametersSHA384, RSA, crypto.SHA384, true},
|
||||||
{SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA512},
|
{SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, pssParametersSHA512, RSA, crypto.SHA512, true},
|
||||||
{DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, DSA, crypto.SHA1},
|
{DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, emptyRawValue, DSA, crypto.SHA1, false},
|
||||||
{DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, DSA, crypto.SHA256},
|
{DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, emptyRawValue, DSA, crypto.SHA256, false},
|
||||||
{ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1},
|
{ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, emptyRawValue, ECDSA, crypto.SHA1, false},
|
||||||
{ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256},
|
{ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, emptyRawValue, ECDSA, crypto.SHA256, false},
|
||||||
{ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384},
|
{ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, emptyRawValue, ECDSA, crypto.SHA384, false},
|
||||||
{ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512},
|
{ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, emptyRawValue, ECDSA, crypto.SHA512, false},
|
||||||
{PureEd25519, "Ed25519", oidSignatureEd25519, Ed25519, crypto.Hash(0) /* no pre-hashing */},
|
{PureEd25519, "Ed25519", oidSignatureEd25519, emptyRawValue, Ed25519, crypto.Hash(0) /* no pre-hashing */, false},
|
||||||
{SM2WithSM3, "SM2-SM3", oidSignatureSM2WithSM3, ECDSA, crypto.Hash(0) /* no pre-hashing */},
|
{SM2WithSM3, "SM2-SM3", oidSignatureSM2WithSM3, emptyRawValue, ECDSA, crypto.Hash(0) /* no pre-hashing */, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashToPSSParameters contains the DER encoded RSA PSS parameters for the
|
var emptyRawValue = asn1.RawValue{}
|
||||||
|
|
||||||
|
// DER encoded RSA PSS parameters for the
|
||||||
// SHA256, SHA384, and SHA512 hashes as defined in RFC 3447, Appendix A.2.3.
|
// SHA256, SHA384, and SHA512 hashes as defined in RFC 3447, Appendix A.2.3.
|
||||||
// The parameters contain the following values:
|
// The parameters contain the following values:
|
||||||
// - hashAlgorithm contains the associated hash identifier with NULL parameters
|
// - hashAlgorithm contains the associated hash identifier with NULL parameters
|
||||||
// - maskGenAlgorithm always contains the default mgf1SHA1 identifier
|
// - maskGenAlgorithm always contains the default mgf1SHA1 identifier
|
||||||
// - saltLength contains the length of the associated hash
|
// - saltLength contains the length of the associated hash
|
||||||
// - trailerField always contains the default trailerFieldBC value
|
// - trailerField always contains the default trailerFieldBC value
|
||||||
var hashToPSSParameters = map[crypto.Hash]asn1.RawValue{
|
var (
|
||||||
crypto.SHA256: {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}},
|
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}}
|
||||||
crypto.SHA384: {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}},
|
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}}
|
||||||
crypto.SHA512: {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}},
|
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}}
|
||||||
}
|
)
|
||||||
|
|
||||||
// pssParameters reflects the parameters in an AlgorithmIdentifier that
|
// pssParameters reflects the parameters in an AlgorithmIdentifier that
|
||||||
// specifies RSA PSS. See RFC 3447, Appendix A.2.3.
|
// specifies RSA PSS. See RFC 3447, Appendix A.2.3.
|
||||||
@ -885,6 +898,7 @@ var (
|
|||||||
oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
|
oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
|
||||||
oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1}
|
oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1}
|
||||||
oidExtensionCRLNumber = []int{2, 5, 29, 20}
|
oidExtensionCRLNumber = []int{2, 5, 29, 20}
|
||||||
|
oidExtensionReasonCode = []int{2, 5, 29, 21}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -1258,84 +1272,95 @@ func subjectBytes(cert *x509.Certificate) ([]byte, error) {
|
|||||||
return asn1.Marshal(cert.Subject.ToRDNSequence())
|
return asn1.Marshal(cert.Subject.ToRDNSequence())
|
||||||
}
|
}
|
||||||
|
|
||||||
// signingParamsForPublicKey returns the parameters to use for signing with
|
// signingParamsForKey returns the signature algorithm and its Algorithm
|
||||||
// priv. If requestedSigAlgo is not zero then it overrides the default
|
// Identifier to use for signing, based on the key type. If sigAlgo is not zero
|
||||||
// signature algorithm.
|
// then it overrides the default.
|
||||||
func signingParamsForPublicKey(pub any, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
|
func signingParamsForKey(key crypto.Signer, sigAlgo SignatureAlgorithm) (SignatureAlgorithm, pkix.AlgorithmIdentifier, error) {
|
||||||
|
var ai pkix.AlgorithmIdentifier
|
||||||
var pubType PublicKeyAlgorithm
|
var pubType PublicKeyAlgorithm
|
||||||
|
var defaultAlgo SignatureAlgorithm
|
||||||
|
|
||||||
switch pub := pub.(type) {
|
switch pub := key.Public().(type) {
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
pubType = RSA
|
pubType = RSA
|
||||||
hashFunc = crypto.SHA256
|
defaultAlgo = SHA256WithRSA
|
||||||
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
|
|
||||||
sigAlgo.Parameters = asn1.NullRawValue
|
|
||||||
|
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
pubType = ECDSA
|
pubType = ECDSA
|
||||||
|
|
||||||
switch pub.Curve {
|
switch pub.Curve {
|
||||||
case elliptic.P224(), elliptic.P256():
|
case elliptic.P224(), elliptic.P256():
|
||||||
hashFunc = crypto.SHA256
|
defaultAlgo = ECDSAWithSHA256
|
||||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
|
|
||||||
case elliptic.P384():
|
case elliptic.P384():
|
||||||
hashFunc = crypto.SHA384
|
defaultAlgo = ECDSAWithSHA384
|
||||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
|
|
||||||
case elliptic.P521():
|
case elliptic.P521():
|
||||||
hashFunc = crypto.SHA512
|
defaultAlgo = ECDSAWithSHA512
|
||||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
|
|
||||||
case sm2.P256():
|
case sm2.P256():
|
||||||
hashFunc = crypto.Hash(0)
|
defaultAlgo = SM2WithSM3
|
||||||
sigAlgo.Algorithm = oidSignatureSM2WithSM3
|
|
||||||
default:
|
default:
|
||||||
err = errors.New("x509: unknown elliptic curve")
|
return 0, ai, errors.New("x509: unsupported elliptic curve")
|
||||||
}
|
}
|
||||||
|
|
||||||
case ed25519.PublicKey:
|
case ed25519.PublicKey:
|
||||||
pubType = Ed25519
|
pubType = Ed25519
|
||||||
sigAlgo.Algorithm = oidSignatureEd25519
|
defaultAlgo = PureEd25519
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = errors.New("x509: only RSA, ECDSA and Ed25519 keys supported")
|
return 0, ai, errors.New("x509: only RSA, ECDSA and Ed25519 keys supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if sigAlgo == 0 {
|
||||||
return
|
sigAlgo = defaultAlgo
|
||||||
}
|
}
|
||||||
|
|
||||||
if requestedSigAlgo == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, details := range signatureAlgorithmDetails {
|
for _, details := range signatureAlgorithmDetails {
|
||||||
if details.algo == requestedSigAlgo {
|
if details.algo == sigAlgo {
|
||||||
if details.pubKeyAlgo != pubType {
|
if details.pubKeyAlgo != pubType {
|
||||||
err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
|
return 0, ai, errors.New("x509: requested SignatureAlgorithm does not match private key type")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
sigAlgo.Algorithm, hashFunc = details.oid, details.hash
|
if details.hash == crypto.MD5 {
|
||||||
if hashFunc == 0 && pubType != Ed25519 && !sigAlgo.Algorithm.Equal(oidSignatureSM2WithSM3) {
|
return 0, ai, errors.New("x509: signing with MD5 is not supported")
|
||||||
err = errors.New("x509: cannot sign with hash function requested")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if hashFunc == crypto.MD5 {
|
|
||||||
err = errors.New("x509: signing with MD5 is not supported")
|
return sigAlgo, pkix.AlgorithmIdentifier{
|
||||||
return
|
Algorithm: details.oid,
|
||||||
}
|
Parameters: details.params,
|
||||||
if isRSAPSS(requestedSigAlgo) {
|
}, nil
|
||||||
sigAlgo.Parameters = hashToPSSParameters[hashFunc]
|
|
||||||
}
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
return 0, ai, errors.New("x509: unknown SignatureAlgorithm")
|
||||||
err = errors.New("x509: unknown SignatureAlgorithm")
|
}
|
||||||
|
|
||||||
|
func signTBS(tbs []byte, key crypto.Signer, sigAlg SignatureAlgorithm, rand io.Reader) ([]byte, error) {
|
||||||
|
signed := tbs
|
||||||
|
hashFunc := hashFunc(sigAlg)
|
||||||
|
if hashFunc != 0 {
|
||||||
|
h := hashFunc.New()
|
||||||
|
h.Write(signed)
|
||||||
|
signed = h.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
var signerOpts crypto.SignerOpts = hashFunc
|
||||||
|
if isRSAPSS(sigAlg) {
|
||||||
|
signerOpts = &rsa.PSSOptions{
|
||||||
|
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||||
|
Hash: hashFunc,
|
||||||
|
}
|
||||||
|
} else if sigAlg == SM2WithSM3 {
|
||||||
|
signerOpts = sm2.DefaultSM2SignerOpts
|
||||||
|
}
|
||||||
|
|
||||||
|
signature, err := key.Sign(rand, signed, signerOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the signature to ensure the crypto.Signer behaved correctly.
|
||||||
|
if err := checkSignature(sigAlg, tbs, signature, key.Public(), true); err != nil {
|
||||||
|
return nil, fmt.Errorf("x509: signature returned by signer is invalid: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return signature, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is
|
// emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is
|
||||||
@ -1345,38 +1370,38 @@ var emptyASN1Subject = []byte{0x30, 0}
|
|||||||
// CreateCertificate creates a new X.509 v3 certificate based on a template.
|
// CreateCertificate creates a new X.509 v3 certificate based on a template.
|
||||||
// The following members of template are currently used:
|
// The following members of template are currently used:
|
||||||
//
|
//
|
||||||
// - AuthorityKeyId
|
// - AuthorityKeyId
|
||||||
// - BasicConstraintsValid
|
// - BasicConstraintsValid
|
||||||
// - CRLDistributionPoints
|
// - CRLDistributionPoints
|
||||||
// - DNSNames
|
// - DNSNames
|
||||||
// - EmailAddresses
|
// - EmailAddresses
|
||||||
// - ExcludedDNSDomains
|
// - ExcludedDNSDomains
|
||||||
// - ExcludedEmailAddresses
|
// - ExcludedEmailAddresses
|
||||||
// - ExcludedIPRanges
|
// - ExcludedIPRanges
|
||||||
// - ExcludedURIDomains
|
// - ExcludedURIDomains
|
||||||
// - ExtKeyUsage
|
// - ExtKeyUsage
|
||||||
// - ExtraExtensions
|
// - ExtraExtensions
|
||||||
// - IPAddresses
|
// - IPAddresses
|
||||||
// - IsCA
|
// - IsCA
|
||||||
// - IssuingCertificateURL
|
// - IssuingCertificateURL
|
||||||
// - KeyUsage
|
// - KeyUsage
|
||||||
// - MaxPathLen
|
// - MaxPathLen
|
||||||
// - MaxPathLenZero
|
// - MaxPathLenZero
|
||||||
// - NotAfter
|
// - NotAfter
|
||||||
// - NotBefore
|
// - NotBefore
|
||||||
// - OCSPServer
|
// - OCSPServer
|
||||||
// - PermittedDNSDomains
|
// - PermittedDNSDomains
|
||||||
// - PermittedDNSDomainsCritical
|
// - PermittedDNSDomainsCritical
|
||||||
// - PermittedEmailAddresses
|
// - PermittedEmailAddresses
|
||||||
// - PermittedIPRanges
|
// - PermittedIPRanges
|
||||||
// - PermittedURIDomains
|
// - PermittedURIDomains
|
||||||
// - PolicyIdentifiers
|
// - PolicyIdentifiers
|
||||||
// - SerialNumber
|
// - SerialNumber
|
||||||
// - SignatureAlgorithm
|
// - SignatureAlgorithm
|
||||||
// - Subject
|
// - Subject
|
||||||
// - SubjectKeyId
|
// - SubjectKeyId
|
||||||
// - URIs
|
// - URIs
|
||||||
// - UnknownExtKeyUsage
|
// - UnknownExtKeyUsage
|
||||||
//
|
//
|
||||||
// The certificate is signed by parent. If parent is equal to template then the
|
// The certificate is signed by parent. If parent is equal to template then the
|
||||||
// certificate is self-signed, both parent and template should be *x509.Certificate or
|
// certificate is self-signed, both parent and template should be *x509.Certificate or
|
||||||
@ -1428,7 +1453,7 @@ func CreateCertificate(rand io.Reader, template, parent, pub, priv any) ([]byte,
|
|||||||
return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen")
|
return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), realTemplate.SignatureAlgorithm)
|
signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(key, realTemplate.SignatureAlgorithm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1487,7 +1512,7 @@ func CreateCertificate(rand io.Reader, template, parent, pub, priv any) ([]byte,
|
|||||||
c := tbsCertificate{
|
c := tbsCertificate{
|
||||||
Version: 2,
|
Version: 2,
|
||||||
SerialNumber: realTemplate.SerialNumber,
|
SerialNumber: realTemplate.SerialNumber,
|
||||||
SignatureAlgorithm: signatureAlgorithm,
|
SignatureAlgorithm: algorithmIdentifier,
|
||||||
Issuer: asn1.RawValue{FullBytes: asn1Issuer},
|
Issuer: asn1.RawValue{FullBytes: asn1Issuer},
|
||||||
Validity: validity{realTemplate.NotBefore.UTC(), realTemplate.NotAfter.UTC()},
|
Validity: validity{realTemplate.NotBefore.UTC(), realTemplate.NotAfter.UTC()},
|
||||||
Subject: asn1.RawValue{FullBytes: asn1Subject},
|
Subject: asn1.RawValue{FullBytes: asn1Subject},
|
||||||
@ -1501,44 +1526,15 @@ func CreateCertificate(rand io.Reader, template, parent, pub, priv any) ([]byte,
|
|||||||
}
|
}
|
||||||
c.Raw = tbsCertContents
|
c.Raw = tbsCertContents
|
||||||
|
|
||||||
signed := tbsCertContents
|
signature, err := signTBS(tbsCertContents, key, signatureAlgorithm, rand)
|
||||||
|
|
||||||
var signature []byte
|
|
||||||
if hashFunc != 0 {
|
|
||||||
h := hashFunc.New()
|
|
||||||
h.Write(signed)
|
|
||||||
signed = h.Sum(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
var signerOpts crypto.SignerOpts = hashFunc
|
|
||||||
if realTemplate.SignatureAlgorithm != 0 && isRSAPSS(realTemplate.SignatureAlgorithm) {
|
|
||||||
signerOpts = &rsa.PSSOptions{
|
|
||||||
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
|
||||||
Hash: hashFunc,
|
|
||||||
}
|
|
||||||
} else if signatureAlgorithm.Algorithm.Equal(oidSignatureSM2WithSM3) {
|
|
||||||
signerOpts = sm2.DefaultSM2SignerOpts
|
|
||||||
}
|
|
||||||
signature, err = key.Sign(rand, signed, signerOpts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return asn1.Marshal(certificate{
|
||||||
signedCert, err := asn1.Marshal(certificate{
|
TBSCertificate: c,
|
||||||
c,
|
SignatureAlgorithm: algorithmIdentifier,
|
||||||
signatureAlgorithm,
|
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
||||||
asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the signature to ensure the crypto.Signer behaved correctly.
|
|
||||||
if err := checkSignature(getSignatureAlgorithmFromAI(signatureAlgorithm), c.Raw, signature, key.Public(), true); err != nil {
|
|
||||||
return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return signedCert, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toCertificate(in any) (*x509.Certificate, error) {
|
func toCertificate(in any) (*x509.Certificate, error) {
|
||||||
@ -1576,7 +1572,7 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.Re
|
|||||||
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
|
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0)
|
signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(key, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1590,7 +1586,7 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.Re
|
|||||||
|
|
||||||
tbsCertList := pkix.TBSCertificateList{
|
tbsCertList := pkix.TBSCertificateList{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
Signature: signatureAlgorithm,
|
Signature: algorithmIdentifier,
|
||||||
Issuer: c.Subject.ToRDNSequence(),
|
Issuer: c.Subject.ToRDNSequence(),
|
||||||
ThisUpdate: now.UTC(),
|
ThisUpdate: now.UTC(),
|
||||||
NextUpdate: expiry.UTC(),
|
NextUpdate: expiry.UTC(),
|
||||||
@ -1603,34 +1599,25 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.Re
|
|||||||
aki.Id = oidExtensionAuthorityKeyId
|
aki.Id = oidExtensionAuthorityKeyId
|
||||||
aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId})
|
aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
tbsCertList.Extensions = append(tbsCertList.Extensions, aki)
|
tbsCertList.Extensions = append(tbsCertList.Extensions, aki)
|
||||||
}
|
}
|
||||||
|
|
||||||
tbsCertListContents, err := asn1.Marshal(tbsCertList)
|
tbsCertListContents, err := asn1.Marshal(tbsCertList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
signed := tbsCertListContents
|
tbsCertList.Raw = tbsCertListContents
|
||||||
var opts crypto.SignerOpts = hashFunc
|
signature, err := signTBS(tbsCertListContents, key, signatureAlgorithm, rand)
|
||||||
if signatureAlgorithm.Algorithm.Equal(oidSignatureSM2WithSM3) {
|
|
||||||
opts = sm2.DefaultSM2SignerOpts
|
|
||||||
}
|
|
||||||
if hashFunc != 0 {
|
|
||||||
h := hashFunc.New()
|
|
||||||
h.Write(signed)
|
|
||||||
signed = h.Sum(nil)
|
|
||||||
}
|
|
||||||
signature, err := key.Sign(rand, signed, opts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return asn1.Marshal(pkix.CertificateList{
|
return asn1.Marshal(pkix.CertificateList{
|
||||||
TBSCertList: tbsCertList,
|
TBSCertList: tbsCertList,
|
||||||
SignatureAlgorithm: signatureAlgorithm,
|
SignatureAlgorithm: algorithmIdentifier,
|
||||||
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1745,14 +1732,14 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error)
|
|||||||
// CreateCertificateRequest creates a new certificate request based on a
|
// CreateCertificateRequest creates a new certificate request based on a
|
||||||
// template. The following members of template are used:
|
// template. The following members of template are used:
|
||||||
//
|
//
|
||||||
// - SignatureAlgorithm
|
// - SignatureAlgorithm
|
||||||
// - Subject
|
// - Subject
|
||||||
// - DNSNames
|
// - DNSNames
|
||||||
// - EmailAddresses
|
// - EmailAddresses
|
||||||
// - IPAddresses
|
// - IPAddresses
|
||||||
// - URIs
|
// - URIs
|
||||||
// - ExtraExtensions
|
// - ExtraExtensions
|
||||||
// - Attributes (deprecated)
|
// - Attributes (deprecated)
|
||||||
//
|
//
|
||||||
// priv is the private key to sign the CSR with, and the corresponding public
|
// priv is the private key to sign the CSR with, and the corresponding public
|
||||||
// key will be included in the CSR. It must implement crypto.Signer and its
|
// key will be included in the CSR. It must implement crypto.Signer and its
|
||||||
@ -1767,9 +1754,7 @@ func CreateCertificateRequest(rand io.Reader, template *x509.CertificateRequest,
|
|||||||
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
|
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
|
||||||
}
|
}
|
||||||
|
|
||||||
var hashFunc crypto.Hash
|
signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(key, template.SignatureAlgorithm)
|
||||||
var sigAlgo pkix.AlgorithmIdentifier
|
|
||||||
hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1841,7 +1826,7 @@ func CreateCertificateRequest(rand io.Reader, template *x509.CertificateRequest,
|
|||||||
|
|
||||||
rawAttributes, err := newRawAttributes(attributes)
|
rawAttributes, err := newRawAttributes(attributes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not included in attributes, add a new attribute for the
|
// If not included in attributes, add a new attribute for the
|
||||||
@ -1891,30 +1876,18 @@ func CreateCertificateRequest(rand io.Reader, template *x509.CertificateRequest,
|
|||||||
|
|
||||||
tbsCSRContents, err := asn1.Marshal(tbsCSR)
|
tbsCSRContents, err := asn1.Marshal(tbsCSR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
tbsCSR.Raw = tbsCSRContents
|
tbsCSR.Raw = tbsCSRContents
|
||||||
|
|
||||||
signed := tbsCSRContents
|
signature, err := signTBS(tbsCSRContents, key, signatureAlgorithm, rand)
|
||||||
var opts crypto.SignerOpts = hashFunc
|
|
||||||
if hashFunc != 0 {
|
|
||||||
h := hashFunc.New()
|
|
||||||
h.Write(signed)
|
|
||||||
signed = h.Sum(nil)
|
|
||||||
}
|
|
||||||
if sigAlgo.Algorithm.Equal(oidSignatureSM2WithSM3) {
|
|
||||||
opts = sm2.DefaultSM2SignerOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
var signature []byte
|
|
||||||
signature, err = key.Sign(rand, signed, opts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return asn1.Marshal(certificateRequest{
|
return asn1.Marshal(certificateRequest{
|
||||||
TBSCSR: tbsCSR,
|
TBSCSR: tbsCSR,
|
||||||
SignatureAlgorithm: sigAlgo,
|
SignatureAlgorithm: algorithmIdentifier,
|
||||||
SignatureValue: asn1.BitString{
|
SignatureValue: asn1.BitString{
|
||||||
Bytes: signature,
|
Bytes: signature,
|
||||||
BitLength: len(signature) * 8,
|
BitLength: len(signature) * 8,
|
||||||
@ -2057,18 +2030,70 @@ func CreateRevocationList(rand io.Reader, template *x509.RevocationList, issuer
|
|||||||
return nil, errors.New("x509: template contains nil Number field")
|
return nil, errors.New("x509: template contains nil Number field")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
|
signatureAlgorithm, algorithmIdentifier, err := signingParamsForKey(priv, template.SignatureAlgorithm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force revocation times to UTC per RFC 5280.
|
var revokedCerts []pkix.RevokedCertificate
|
||||||
revokedCertsUTC := make([]pkix.RevokedCertificate, len(template.RevokedCertificates))
|
// Only process the deprecated RevokedCertificates field if it is populated
|
||||||
for i, rc := range template.RevokedCertificates {
|
// and the new RevokedCertificateEntries field is not populated.
|
||||||
rc.RevocationTime = rc.RevocationTime.UTC()
|
if len(template.RevokedCertificates) > 0 && len(template.RevokedCertificateEntries) == 0 {
|
||||||
revokedCertsUTC[i] = rc
|
// Force revocation times to UTC per RFC 5280.
|
||||||
|
revokedCerts = make([]pkix.RevokedCertificate, len(template.RevokedCertificates))
|
||||||
|
for i, rc := range template.RevokedCertificates {
|
||||||
|
rc.RevocationTime = rc.RevocationTime.UTC()
|
||||||
|
revokedCerts[i] = rc
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Convert the ReasonCode field to a proper extension, and force revocation
|
||||||
|
// times to UTC per RFC 5280.
|
||||||
|
revokedCerts = make([]pkix.RevokedCertificate, len(template.RevokedCertificateEntries))
|
||||||
|
for i, rce := range template.RevokedCertificateEntries {
|
||||||
|
if rce.SerialNumber == nil {
|
||||||
|
return nil, errors.New("x509: template contains entry with nil SerialNumber field")
|
||||||
|
}
|
||||||
|
if rce.RevocationTime.IsZero() {
|
||||||
|
return nil, errors.New("x509: template contains entry with zero RevocationTime field")
|
||||||
|
}
|
||||||
|
|
||||||
|
rc := pkix.RevokedCertificate{
|
||||||
|
SerialNumber: rce.SerialNumber,
|
||||||
|
RevocationTime: rce.RevocationTime.UTC(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over any extra extensions, except for a Reason Code extension,
|
||||||
|
// because we'll synthesize that ourselves to ensure it is correct.
|
||||||
|
exts := make([]pkix.Extension, 0, len(rce.ExtraExtensions))
|
||||||
|
for _, ext := range rce.ExtraExtensions {
|
||||||
|
if ext.Id.Equal(oidExtensionReasonCode) {
|
||||||
|
return nil, errors.New("x509: template contains entry with ReasonCode ExtraExtension; use ReasonCode field instead")
|
||||||
|
}
|
||||||
|
exts = append(exts, ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only add a reasonCode extension if the reason is non-zero, as per
|
||||||
|
// RFC 5280 Section 5.3.1.
|
||||||
|
if rce.ReasonCode != 0 {
|
||||||
|
reasonBytes, err := asn1.Marshal(asn1.Enumerated(rce.ReasonCode))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
exts = append(exts, pkix.Extension{
|
||||||
|
Id: oidExtensionReasonCode,
|
||||||
|
Value: reasonBytes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(exts) > 0 {
|
||||||
|
rc.Extensions = exts
|
||||||
|
}
|
||||||
|
revokedCerts[i] = rc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aki, err := asn1.Marshal(authKeyId{Id: issuer.SubjectKeyId})
|
aki, err := asn1.Marshal(authKeyId{Id: issuer.SubjectKeyId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -2089,7 +2114,7 @@ func CreateRevocationList(rand io.Reader, template *x509.RevocationList, issuer
|
|||||||
|
|
||||||
tbsCertList := tbsCertificateList{
|
tbsCertList := tbsCertificateList{
|
||||||
Version: 1, // v2
|
Version: 1, // v2
|
||||||
Signature: signatureAlgorithm,
|
Signature: algorithmIdentifier,
|
||||||
Issuer: asn1.RawValue{FullBytes: issuerSubject},
|
Issuer: asn1.RawValue{FullBytes: issuerSubject},
|
||||||
ThisUpdate: template.ThisUpdate.UTC(),
|
ThisUpdate: template.ThisUpdate.UTC(),
|
||||||
NextUpdate: template.NextUpdate.UTC(),
|
NextUpdate: template.NextUpdate.UTC(),
|
||||||
@ -2104,8 +2129,8 @@ func CreateRevocationList(rand io.Reader, template *x509.RevocationList, issuer
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if len(revokedCertsUTC) > 0 {
|
if len(revokedCerts) > 0 {
|
||||||
tbsCertList.RevokedCertificates = revokedCertsUTC
|
tbsCertList.RevokedCertificates = revokedCerts
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(template.ExtraExtensions) > 0 {
|
if len(template.ExtraExtensions) > 0 {
|
||||||
@ -2121,30 +2146,14 @@ func CreateRevocationList(rand io.Reader, template *x509.RevocationList, issuer
|
|||||||
// then embedding in certificateList below.
|
// then embedding in certificateList below.
|
||||||
tbsCertList.Raw = tbsCertListContents
|
tbsCertList.Raw = tbsCertListContents
|
||||||
|
|
||||||
input := tbsCertListContents
|
signature, err := signTBS(tbsCertListContents, priv, signatureAlgorithm, rand)
|
||||||
if hashFunc != 0 {
|
|
||||||
h := hashFunc.New()
|
|
||||||
h.Write(tbsCertListContents)
|
|
||||||
input = h.Sum(nil)
|
|
||||||
}
|
|
||||||
var signerOpts crypto.SignerOpts = hashFunc
|
|
||||||
if isRSAPSS(template.SignatureAlgorithm) {
|
|
||||||
signerOpts = &rsa.PSSOptions{
|
|
||||||
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
|
||||||
Hash: hashFunc,
|
|
||||||
}
|
|
||||||
} else if signatureAlgorithm.Algorithm.Equal(oidSignatureSM2WithSM3) {
|
|
||||||
signerOpts = sm2.DefaultSM2SignerOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
signature, err := priv.Sign(rand, input, signerOpts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return asn1.Marshal(certificateList{
|
return asn1.Marshal(certificateList{
|
||||||
TBSCertList: tbsCertList,
|
TBSCertList: tbsCertList,
|
||||||
SignatureAlgorithm: signatureAlgorithm,
|
SignatureAlgorithm: algorithmIdentifier,
|
||||||
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1099,11 +1099,13 @@ func TestCRLCreation(t *testing.T) {
|
|||||||
crlBytes, err := test.cert.CreateCRL(rand.Reader, test.priv, revokedCerts, now, expiry)
|
crlBytes, err := test.cert.CreateCRL(rand.Reader, test.priv, revokedCerts, now, expiry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: error creating CRL: %s", test.name, err)
|
t.Errorf("%s: error creating CRL: %s", test.name, err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedCRL, err := ParseDERCRL(crlBytes)
|
parsedCRL, err := ParseDERCRL(crlBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: error reparsing CRL: %s", test.name, err)
|
t.Errorf("%s: error reparsing CRL: %s", test.name, err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) {
|
if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) {
|
||||||
t.Errorf("%s: RevokedCertificates mismatch: got %v; want %v.", test.name,
|
t.Errorf("%s: RevokedCertificates mismatch: got %v; want %v.", test.name,
|
||||||
@ -2596,10 +2598,13 @@ func TestRSAPSAParameters(t *testing.T) {
|
|||||||
return serialized
|
return serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
for h, params := range hashToPSSParameters {
|
for _, detail := range signatureAlgorithmDetails {
|
||||||
generated := generateParams(h)
|
if !detail.isRSAPSS {
|
||||||
if !bytes.Equal(params.FullBytes, generated) {
|
continue
|
||||||
t.Errorf("hardcoded parameters for %s didn't match generated parameters: got (generated) %x, wanted (hardcoded) %x", h, generated, params.FullBytes)
|
}
|
||||||
|
generated := generateParams(detail.hash)
|
||||||
|
if !bytes.Equal(detail.params.FullBytes, generated) {
|
||||||
|
t.Errorf("hardcoded parameters for %s didn't match generated parameters: got (generated) %x, wanted (hardcoded) %x", detail.hash, generated, detail.params.FullBytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2730,15 +2735,11 @@ func TestCreateCertificateBrokenSigner(t *testing.T) {
|
|||||||
SerialNumber: big.NewInt(10),
|
SerialNumber: big.NewInt(10),
|
||||||
DNSNames: []string{"example.com"},
|
DNSNames: []string{"example.com"},
|
||||||
}
|
}
|
||||||
k, err := rsa.GenerateKey(rand.Reader, 1024)
|
expectedErr := "signature returned by signer is invalid"
|
||||||
if err != nil {
|
_, err := CreateCertificate(rand.Reader, template, template, testPrivateKey.Public(), &brokenSigner{testPrivateKey.Public()})
|
||||||
t.Fatalf("failed to generate test key: %s", err)
|
|
||||||
}
|
|
||||||
expectedErr := "x509: signature over certificate returned by signer is invalid: crypto/rsa: verification error"
|
|
||||||
_, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()})
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected CreateCertificate to fail with a broken signer")
|
t.Fatal("expected CreateCertificate to fail with a broken signer")
|
||||||
} else if err.Error() != expectedErr {
|
} else if !strings.Contains(err.Error(), expectedErr) {
|
||||||
t.Fatalf("CreateCertificate returned an unexpected error: got %q, want %q", err, expectedErr)
|
t.Fatalf("CreateCertificate returned an unexpected error: got %q, want %q", err, expectedErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3266,3 +3267,78 @@ func TestDuplicateAttributesCSR(t *testing.T) {
|
|||||||
t.Fatal("ParseCertificateRequest should succeed when parsing CSR with duplicate attributes")
|
t.Fatal("ParseCertificateRequest should succeed when parsing CSR with duplicate attributes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRejectCriticalAKI(t *testing.T) {
|
||||||
|
template := Certificate{
|
||||||
|
SerialNumber: big.NewInt(1),
|
||||||
|
Subject: pkix.Name{CommonName: "Cert"},
|
||||||
|
NotBefore: time.Unix(1000, 0),
|
||||||
|
NotAfter: time.Unix(100000, 0),
|
||||||
|
ExtraExtensions: []pkix.Extension{
|
||||||
|
{
|
||||||
|
Id: asn1.ObjectIdentifier{2, 5, 29, 35},
|
||||||
|
Critical: true,
|
||||||
|
Value: []byte{1, 2, 3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateCertificate() unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
expectedErr := "x509: authority key identifier incorrectly marked critical"
|
||||||
|
_, err = ParseCertificate(certDER)
|
||||||
|
if err == nil || err.Error() != expectedErr {
|
||||||
|
t.Fatalf("ParseCertificate() unexpected error: %v, want: %s", err, expectedErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRejectCriticalAIA(t *testing.T) {
|
||||||
|
template := Certificate{
|
||||||
|
SerialNumber: big.NewInt(1),
|
||||||
|
Subject: pkix.Name{CommonName: "Cert"},
|
||||||
|
NotBefore: time.Unix(1000, 0),
|
||||||
|
NotAfter: time.Unix(100000, 0),
|
||||||
|
ExtraExtensions: []pkix.Extension{
|
||||||
|
{
|
||||||
|
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 1},
|
||||||
|
Critical: true,
|
||||||
|
Value: []byte{1, 2, 3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateCertificate() unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
expectedErr := "x509: authority info access incorrectly marked critical"
|
||||||
|
_, err = ParseCertificate(certDER)
|
||||||
|
if err == nil || err.Error() != expectedErr {
|
||||||
|
t.Fatalf("ParseCertificate() unexpected error: %v, want: %s", err, expectedErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRejectCriticalSKI(t *testing.T) {
|
||||||
|
template := Certificate{
|
||||||
|
SerialNumber: big.NewInt(1),
|
||||||
|
Subject: pkix.Name{CommonName: "Cert"},
|
||||||
|
NotBefore: time.Unix(1000, 0),
|
||||||
|
NotAfter: time.Unix(100000, 0),
|
||||||
|
ExtraExtensions: []pkix.Extension{
|
||||||
|
{
|
||||||
|
Id: asn1.ObjectIdentifier{2, 5, 29, 14},
|
||||||
|
Critical: true,
|
||||||
|
Value: []byte{1, 2, 3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateCertificate() unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
expectedErr := "x509: subject key identifier incorrectly marked critical"
|
||||||
|
_, err = ParseCertificate(certDER)
|
||||||
|
if err == nil || err.Error() != expectedErr {
|
||||||
|
t.Fatalf("ParseCertificate() unexpected error: %v, want: %s", err, expectedErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user