github.com/zmap/zlint@v1.1.0/lints/lint_ecdsa_ee_invalid_ku.go (about) 1 /* 2 * ZLint Copyright 2019 Regents of the University of Michigan 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy 6 * of the License at http://www.apache.org/licenses/LICENSE-2.0 7 * 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 * implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package lints 16 17 import ( 18 "fmt" 19 "sort" 20 "strings" 21 22 "github.com/zmap/zcrypto/x509" 23 "github.com/zmap/zlint/util" 24 ) 25 26 type ecdsaInvalidKU struct{} 27 28 // Initialize is a no-op for this lint. 29 func (l *ecdsaInvalidKU) Initialize() error { 30 return nil 31 } 32 33 // CheckApplies returns true when the certificate is a subscriber cert using an 34 // ECDSA public key algorithm. 35 func (l *ecdsaInvalidKU) CheckApplies(c *x509.Certificate) bool { 36 return util.IsSubscriberCert(c) && c.PublicKeyAlgorithm == x509.ECDSA 37 } 38 39 // Execute returns a Notice level LintResult if the ECDSA end entity certificate 40 // being linted has Key Usage bits set other than digitalSignature, 41 // nonRepudiation/contentCommentment, and keyAgreement. 42 func (l *ecdsaInvalidKU) Execute(c *x509.Certificate) *LintResult { 43 // RFC 5480, Section 3 "Key Usage Bits" says: 44 // 45 // If the keyUsage extension is present in an End Entity (EE) 46 // certificate that indicates id-ecPublicKey in SubjectPublicKeyInfo, 47 // then any combination of the following values MAY be present: 48 // 49 // digitalSignature; 50 // nonRepudiation; and 51 // keyAgreement. 52 // 53 // So we set up `allowedKUs` to match. Note that per RFC 5280: recent editions 54 // of X.509 renamed "nonRepudiation" to "contentCommitment", which is the name 55 // of the Go x509 constant we use here alongside the digitalSignature and 56 // keyAgreement constants. 57 allowedKUs := map[x509.KeyUsage]bool{ 58 x509.KeyUsageDigitalSignature: true, 59 x509.KeyUsageContentCommitment: true, 60 x509.KeyUsageKeyAgreement: true, 61 } 62 63 var invalidKUs []string 64 for ku, kuName := range util.KeyUsageToString { 65 if c.KeyUsage&ku != 0 { 66 if !allowedKUs[ku] { 67 invalidKUs = append(invalidKUs, kuName) 68 } 69 } 70 } 71 72 if len(invalidKUs) > 0 { 73 // Sort the invalid KUs to allow consistent ordering of Details messages for 74 // unit testing 75 sort.Strings(invalidKUs) 76 return &LintResult{ 77 Status: Notice, 78 Details: fmt.Sprintf( 79 "Certificate had unexpected key usage(s): %s", 80 strings.Join(invalidKUs, ", ")), 81 } 82 } 83 84 return &LintResult{ 85 Status: Pass, 86 } 87 } 88 89 func init() { 90 RegisterLint(&Lint{ 91 Name: "n_ecdsa_ee_invalid_ku", 92 Description: "ECDSA end-entity certificates MAY have key usages: digitalSignature, nonRepudiation and keyAgreement", 93 Citation: "RFC 5480 Section 3", 94 Source: RFC5480, 95 EffectiveDate: util.CABEffectiveDate, 96 Lint: &ecdsaInvalidKU{}, 97 }) 98 }