diff --git a/certlib/certlib.go b/certlib/certlib.go index 72c9f15..27cbe00 100644 --- a/certlib/certlib.go +++ b/certlib/certlib.go @@ -14,27 +14,27 @@ import ( func ReadCertificate(in []byte) (cert *x509.Certificate, rest []byte, err error) { if len(in) == 0 { err = certerr.ErrEmptyCertificate - return + return cert, rest, err } if in[0] == '-' { p, remaining := pem.Decode(in) if p == nil { err = errors.New("certlib: invalid PEM file") - return + return cert, rest, err } rest = remaining if p.Type != "CERTIFICATE" { err = certerr.ErrInvalidPEMType(p.Type, "CERTIFICATE") - return + return cert, rest, err } in = p.Bytes } cert, err = x509.ParseCertificate(in) - return + return cert, rest, err } // ReadCertificates tries to read all the certificates in a diff --git a/certlib/helpers.go b/certlib/helpers.go index 5458244..d38e1df 100644 --- a/certlib/helpers.go +++ b/certlib/helpers.go @@ -65,10 +65,10 @@ const OneYear = 8760 * time.Hour // OneDay is a time.Duration representing a day's worth of seconds. const OneDay = 24 * time.Hour -// DelegationUsage is the OID for the DelegationUseage extensions +// DelegationUsage is the OID for the DelegationUseage extensions. var DelegationUsage = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 44} -// DelegationExtension +// DelegationExtension. var DelegationExtension = pkix.Extension{ Id: DelegationUsage, Critical: false, @@ -89,8 +89,8 @@ var Jul2012 = InclusiveDate(2012, time.July, 01) // issuing certificates valid for more than 39 months. var Apr2015 = InclusiveDate(2015, time.April, 01) -// KeyLength returns the bit size of ECDSA or RSA PublicKey -func KeyLength(key interface{}) int { +// KeyLength returns the bit size of ECDSA or RSA PublicKey. +func KeyLength(key any) int { if key == nil { return 0 } @@ -106,7 +106,7 @@ func KeyLength(key interface{}) int { // ExpiryTime returns the time when the certificate chain is expired. func ExpiryTime(chain []*x509.Certificate) (notAfter time.Time) { if len(chain) == 0 { - return + return notAfter } notAfter = chain[0].NotAfter @@ -115,7 +115,7 @@ func ExpiryTime(chain []*x509.Certificate) (notAfter time.Time) { notAfter = cert.NotAfter } } - return + return notAfter } // MonthsValid returns the number of months for which a certificate is valid. @@ -221,7 +221,7 @@ func HashAlgoString(alg x509.SignatureAlgorithm) string { } // StringTLSVersion returns underlying enum values from human names for TLS -// versions, defaults to current golang default of TLS 1.0 +// versions, defaults to current golang default of TLS 1.0. func StringTLSVersion(version string) uint16 { switch version { case "1.2": @@ -233,20 +233,22 @@ func StringTLSVersion(version string) uint16 { } } -// EncodeCertificatesPEM encodes a number of x509 certificates to PEM +// EncodeCertificatesPEM encodes a number of x509 certificates to PEM. func EncodeCertificatesPEM(certs []*x509.Certificate) []byte { var buffer bytes.Buffer for _, cert := range certs { - pem.Encode(&buffer, &pem.Block{ + if err := pem.Encode(&buffer, &pem.Block{ Type: "CERTIFICATE", Bytes: cert.Raw, - }) + }); err != nil { + return nil + } } return buffer.Bytes() } -// EncodeCertificatePEM encodes a single x509 certificates to PEM +// EncodeCertificatePEM encodes a single x509 certificates to PEM. func EncodeCertificatePEM(cert *x509.Certificate) []byte { return EncodeCertificatesPEM([]*x509.Certificate{cert}) } @@ -269,7 +271,10 @@ func ParseCertificatesPEM(certsPEM []byte) ([]*x509.Certificate, error) { certs = append(certs, cert...) } if len(certsPEM) > 0 { - return nil, certerr.DecodeError(certerr.ErrorSourceCertificate, errors.New("trailing data at end of certificate")) + return nil, certerr.DecodeError( + certerr.ErrorSourceCertificate, + errors.New("trailing data at end of certificate"), + ) } return certs, nil } @@ -280,7 +285,8 @@ func ParseCertificatesDER(certsDER []byte, password string) (certs []*x509.Certi certsDER = bytes.TrimSpace(certsDER) pkcs7data, err := pkcs7.ParsePKCS7(certsDER) if err != nil { - var pkcs12data interface{} + var pkcs12data any + var ok bool certs = make([]*x509.Certificate, 1) pkcs12data, certs[0], err = pkcs12.Decode(certsDER, password) if err != nil { @@ -289,7 +295,10 @@ func ParseCertificatesDER(certsDER []byte, password string) (certs []*x509.Certi return nil, nil, certerr.DecodeError(certerr.ErrorSourceCertificate, err) } } else { - key = pkcs12data.(crypto.Signer) + key, ok = pkcs12data.(crypto.Signer) + if !ok { + return nil, nil, certerr.DecodeError(certerr.ErrorSourcePrivateKey, errors.New("PKCS12 data does not contain a private key")) + } } } else { if pkcs7data.ContentInfo != "SignedData" { @@ -338,7 +347,6 @@ func ParseCertificatePEM(certPEM []byte) (*x509.Certificate, error) { // multiple certificates, from the top of certsPEM, which itself may // contain multiple PEM encoded certificate objects. func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, error) { - block, rest := pem.Decode(certsPEM) if block == nil { return nil, rest, nil @@ -441,7 +449,10 @@ func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error) p, rest := pem.Decode(in) if p != nil { if p.Type != "NEW CERTIFICATE REQUEST" && p.Type != "CERTIFICATE REQUEST" { - return nil, rest, certerr.ParsingError(certerr.ErrorSourceCSR, certerr.ErrInvalidPEMType(p.Type, "NEW CERTIFICATE REQUEST", "CERTIFICATE REQUEST")) + return nil, rest, certerr.ParsingError( + certerr.ErrorSourceCSR, + certerr.ErrInvalidPEMType(p.Type, "NEW CERTIFICATE REQUEST", "CERTIFICATE REQUEST"), + ) } csr, err = x509.ParseCertificateRequest(p.Bytes) @@ -509,7 +520,7 @@ func SignerAlgo(priv crypto.Signer) x509.SignatureAlgorithm { } } -// LoadClientCertificate load key/certificate from pem files +// LoadClientCertificate load key/certificate from pem files. func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, error) { if certFile != "" && keyFile != "" { cert, err := tls.LoadX509KeyPair(certFile, keyFile) @@ -521,7 +532,7 @@ func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, e return nil, nil } -// CreateTLSConfig creates a tls.Config object from certs and roots +// CreateTLSConfig creates a tls.Config object from certs and roots. func CreateTLSConfig(remoteCAs *x509.CertPool, cert *tls.Certificate) *tls.Config { var certs []tls.Certificate if cert != nil { @@ -554,7 +565,10 @@ func DeserializeSCTList(serializedSCTList []byte) ([]ct.SignedCertificateTimesta return nil, err } if len(rest) != 0 { - return nil, certerr.ParsingError(certerr.ErrorSourceSCTList, errors.New("serialized SCT list contained trailing garbage")) + return nil, certerr.ParsingError( + certerr.ErrorSourceSCTList, + errors.New("serialized SCT list contained trailing garbage"), + ) } list := make([]ct.SignedCertificateTimestamp, len(sctList.SCTList)) @@ -565,7 +579,10 @@ func DeserializeSCTList(serializedSCTList []byte) ([]ct.SignedCertificateTimesta return nil, err } if len(rest) != 0 { - return nil, certerr.ParsingError(certerr.ErrorSourceSCTList, errors.New("serialized SCT list contained trailing garbage")) + return nil, certerr.ParsingError( + certerr.ErrorSourceSCTList, + errors.New("serialized SCT list contained trailing garbage"), + ) } list[i] = sct } diff --git a/certlib/pkcs7/pkcs7.go b/certlib/pkcs7/pkcs7.go index b4fbdfb..d885677 100644 --- a/certlib/pkcs7/pkcs7.go +++ b/certlib/pkcs7/pkcs7.go @@ -93,7 +93,7 @@ type signedData struct { Version int DigestAlgorithms asn1.RawValue ContentInfo asn1.RawValue - Certificates asn1.RawValue `asn1:"optional" asn1:"tag:0"` + Certificates asn1.RawValue `asn1:"optional"` Crls asn1.RawValue `asn1:"optional"` SignerInfos asn1.RawValue } @@ -207,7 +207,10 @@ func populateEncryptedData(msg *PKCS7, contentBytes []byte) error { return certerr.ParsingError(certerr.ErrorSourceCertificate, err) } if ed.Version != 0 { - return certerr.ParsingError(certerr.ErrorSourceCertificate, errors.New("only PKCS #7 encryptedData version 0 is supported")) + return certerr.ParsingError( + certerr.ErrorSourceCertificate, + errors.New("only PKCS #7 encryptedData version 0 is supported"), + ) } msg.Content.EncryptedData = ed return nil @@ -216,7 +219,6 @@ func populateEncryptedData(msg *PKCS7, contentBytes []byte) error { // ParsePKCS7 attempts to parse the DER encoded bytes of a // PKCS7 structure. func ParsePKCS7(raw []byte) (msg *PKCS7, err error) { - pkcs7, err := unmarshalInit(raw) if err != nil { return nil, err @@ -240,9 +242,11 @@ func ParsePKCS7(raw []byte) (msg *PKCS7, err error) { return nil, err } default: - return nil, certerr.ParsingError(certerr.ErrorSourceCertificate, errors.New("only PKCS# 7 content of type data, signed data or encrypted data can be parsed")) + return nil, certerr.ParsingError( + certerr.ErrorSourceCertificate, + errors.New("only PKCS# 7 content of type data, signed data or encrypted data can be parsed"), + ) } return msg, nil - } diff --git a/certlib/revoke/revoke.go b/certlib/revoke/revoke.go index b32123b..65b55ea 100644 --- a/certlib/revoke/revoke.go +++ b/certlib/revoke/revoke.go @@ -89,7 +89,7 @@ func ldapURL(url string) bool { // - false, false: an error was encountered while checking revocations. // - false, true: the certificate was checked successfully, and it is not revoked. // - true, true: the certificate was checked successfully, and it is revoked. -// - true, false: failure to check revocation status causes verification to fail +// - true, false: failure to check revocation status causes verification to fail. func revCheck(cert *x509.Certificate) (revoked, ok bool, err error) { for _, url := range cert.CRLDistributionPoints { if ldapURL(url) { @@ -154,7 +154,6 @@ func getIssuer(cert *x509.Certificate) *x509.Certificate { } return issuer - } // check a cert against a specific CRL. Returns the same bool pair @@ -219,16 +218,16 @@ func VerifyCertificate(cert *x509.Certificate) (revoked, ok bool) { // VerifyCertificateError ensures that the certificate passed in hasn't // expired and checks the CRL for the server. func VerifyCertificateError(cert *x509.Certificate) (revoked, ok bool, err error) { - if !time.Now().Before(cert.NotAfter) { - msg := fmt.Sprintf("Certificate expired %s\n", cert.NotAfter) - log.Info(msg) - return true, true, errors.New(msg) - } else if !time.Now().After(cert.NotBefore) { - msg := fmt.Sprintf("Certificate isn't valid until %s\n", cert.NotBefore) - log.Info(msg) - return true, true, errors.New(msg) - } - return revCheck(cert) + if !time.Now().Before(cert.NotAfter) { + msg := fmt.Sprintf("Certificate expired %s\n", cert.NotAfter) + log.Info(msg) + return true, true, errors.New(msg) + } else if !time.Now().After(cert.NotBefore) { + msg := fmt.Sprintf("Certificate isn't valid until %s\n", cert.NotBefore) + log.Info(msg) + return true, true, errors.New(msg) + } + return revCheck(cert) } func fetchRemote(url string) (*x509.Certificate, error) { @@ -343,21 +342,21 @@ func sendOCSPRequest(server string, req []byte, leaf, issuer *x509.Certificate) var crlRead = io.ReadAll -// SetCRLFetcher sets the function to use to read from the http response body +// SetCRLFetcher sets the function to use to read from the http response body. func SetCRLFetcher(fn func(io.Reader) ([]byte, error)) { crlRead = fn } var remoteRead = io.ReadAll -// SetRemoteFetcher sets the function to use to read from the http response body +// SetRemoteFetcher sets the function to use to read from the http response body. func SetRemoteFetcher(fn func(io.Reader) ([]byte, error)) { remoteRead = fn } var ocspRead = io.ReadAll -// SetOCSPFetcher sets the function to use to read from the http response body +// SetOCSPFetcher sets the function to use to read from the http response body. func SetOCSPFetcher(fn func(io.Reader) ([]byte, error)) { ocspRead = fn } diff --git a/certlib/revoke/revoke_test.go b/certlib/revoke/revoke_test.go index 145634f..c872e2c 100644 --- a/certlib/revoke/revoke_test.go +++ b/certlib/revoke/revoke_test.go @@ -50,7 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // to indicate that this is the case. // 2014/05/22 14:18:17 Certificate expired 2014-04-04 14:14:20 +0000 UTC -// 2014/05/22 14:18:17 Revoked certificate: misc/intermediate_ca/ActalisServerAuthenticationCA.crt +// 2014/05/22 14:18:17 Revoked certificate: misc/intermediate_ca/ActalisServerAuthenticationCA.crt. var expiredCert = mustParse(`-----BEGIN CERTIFICATE----- MIIEXTCCA8agAwIBAgIEBycURTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU @@ -80,7 +80,7 @@ sESPRwHkcMUNdAp37FLweUw= // 2014/05/22 14:18:31 Serial number match: intermediate is revoked. // 2014/05/22 14:18:31 certificate is revoked via CRL -// 2014/05/22 14:18:31 Revoked certificate: misc/intermediate_ca/MobileArmorEnterpriseCA.crt +// 2014/05/22 14:18:31 Revoked certificate: misc/intermediate_ca/MobileArmorEnterpriseCA.crt. var revokedCert = mustParse(`-----BEGIN CERTIFICATE----- MIIEEzCCAvugAwIBAgILBAAAAAABGMGjftYwDQYJKoZIhvcNAQEFBQAwcTEoMCYG A1UEAxMfR2xvYmFsU2lnbiBSb290U2lnbiBQYXJ0bmVycyBDQTEdMBsGA1UECxMU @@ -106,7 +106,7 @@ Kz5vh+5tmytUPKA8hUgmLWe94lMb7Uqq2wgZKsqun5DAWleKu81w7wEcOrjiiB+x jeBHq7OnpWm+ccTOPCE6H4ZN4wWVS7biEBUdop/8HgXBPQHWAdjL -----END CERTIFICATE-----`) -// A Comodo intermediate CA certificate with issuer url, CRL url and OCSP url +// A Comodo intermediate CA certificate with issuer url, CRL url and OCSP url. var goodComodoCA = (`-----BEGIN CERTIFICATE----- MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G @@ -182,7 +182,6 @@ func TestGood(t *testing.T) { } else if revoked { t.Fatalf("good certificate should not have been marked as revoked") } - } func TestLdap(t *testing.T) { @@ -230,7 +229,6 @@ func TestBadCRLSet(t *testing.T) { t.Fatalf("key emptystring should be deleted from CRLSet") } delete(CRLSet, "") - } func TestCachedCRLSet(t *testing.T) { @@ -241,13 +239,11 @@ func TestCachedCRLSet(t *testing.T) { } func TestRemoteFetchError(t *testing.T) { - badurl := ":" if _, err := fetchRemote(badurl); err == nil { t.Fatalf("fetching bad url should result in non-nil error") } - } func TestNoOCSPServers(t *testing.T) {