134 lines
5.9 KiB
Go
134 lines
5.9 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the go/golang LICENSE file.
|
|
|
|
package pkcs7
|
|
|
|
// These are private constants and functions from the crypto/x509 package that
|
|
// are useful when dealing with signatures verified by x509 certificates
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/asn1"
|
|
)
|
|
|
|
var (
|
|
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}
|
|
|
|
oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
|
|
oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
|
|
oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
|
|
|
|
oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8}
|
|
|
|
// oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA
|
|
// but it's specified by ISO. Microsoft's makecert.exe has been known
|
|
// to produce certificates with this OID.
|
|
oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29}
|
|
)
|
|
|
|
var 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},
|
|
}
|
|
|
|
// pssParameters reflects the parameters in an AlgorithmIdentifier that
|
|
// specifies RSA PSS. See https://tools.ietf.org/html/rfc3447#appendix-A.2.3
|
|
type pssParameters struct {
|
|
// The following three fields are not marked as
|
|
// optional because the default values specify SHA-1,
|
|
// which is no longer suitable for use in signatures.
|
|
Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"`
|
|
MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"`
|
|
SaltLength int `asn1:"explicit,tag:2"`
|
|
TrailerField int `asn1:"optional,explicit,tag:3,default:1"`
|
|
}
|
|
|
|
// asn1.NullBytes is not available prior to Go 1.9
|
|
var nullBytes = []byte{5, 0}
|
|
|
|
func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) x509.SignatureAlgorithm {
|
|
if !ai.Algorithm.Equal(oidSignatureRSAPSS) {
|
|
for _, details := range signatureAlgorithmDetails {
|
|
if ai.Algorithm.Equal(details.oid) {
|
|
return details.algo
|
|
}
|
|
}
|
|
return x509.UnknownSignatureAlgorithm
|
|
}
|
|
|
|
// RSA PSS is special because it encodes important parameters
|
|
// in the Parameters.
|
|
|
|
var params pssParameters
|
|
if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, ¶ms); err != nil {
|
|
return x509.UnknownSignatureAlgorithm
|
|
}
|
|
|
|
var mgf1HashFunc pkix.AlgorithmIdentifier
|
|
if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil {
|
|
return x509.UnknownSignatureAlgorithm
|
|
}
|
|
|
|
// PSS is greatly overburdened with options. This code forces
|
|
// them into three buckets by requiring that the MGF1 hash
|
|
// function always match the message hash function (as
|
|
// recommended in
|
|
// https://tools.ietf.org/html/rfc3447#section-8.1), that the
|
|
// salt length matches the hash length, and that the trailer
|
|
// field has the default value.
|
|
if !bytes.Equal(params.Hash.Parameters.FullBytes, nullBytes) ||
|
|
!params.MGF.Algorithm.Equal(oidMGF1) ||
|
|
!mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) ||
|
|
!bytes.Equal(mgf1HashFunc.Parameters.FullBytes, nullBytes) ||
|
|
params.TrailerField != 1 {
|
|
return x509.UnknownSignatureAlgorithm
|
|
}
|
|
|
|
switch {
|
|
case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32:
|
|
return x509.SHA256WithRSAPSS
|
|
case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48:
|
|
return x509.SHA384WithRSAPSS
|
|
case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64:
|
|
return x509.SHA512WithRSAPSS
|
|
}
|
|
|
|
return x509.UnknownSignatureAlgorithm
|
|
}
|