From 25b534a6b2a2d350ece9e32b8721e7aa71b4b62a Mon Sep 17 00:00:00 2001 From: Rawlin Peters Date: Mon, 18 Mar 2019 12:14:41 -0600 Subject: [PATCH 01/18] Fix add sslkeys endpoint to always use the input certificate Sometimes, the Certificate.Verify method will remove elements from a valid certificate chain. Instead of using the output of that method, always use the user input certificate and return a warning if the input certificate does not match the output of the Certificate.Verify method. Fixes #3398 (cherry picked from commit dde742ec2a9c6fff5477b5a982a6ac4a58cd83a1) --- .../deliveryservice/keys.go | 40 ++++++++++++------- .../deliveryservice/keys_test.go | 13 ++++-- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 7a820146ea..1923d3eebd 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -59,7 +59,7 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr) return } - certChain, isUnknownAuth, err := verifyCertificate(req.Certificate.Crt, "") + certChain, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertificate(req.Certificate.Crt, "") if err != nil { api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("verifying certificate: "+err.Error()), nil) return @@ -83,7 +83,11 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { return } if isUnknownAuth { - api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were successfully added for '"+*req.DeliveryService+"', but the certificate is signed by an unknown authority and may be invalid") + api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were successfully added for '"+*req.DeliveryService+"', but the input certificate may be invalid (certificate is signed by an unknown authority)") + return + } + if isVerifiedChainNotEqual { + api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were successfully added for '"+*req.DeliveryService+"', but the input certificate may be invalid (certificate verification produced a different chain)") return } api.WriteResp(w, r, "Successfully added ssl keys for "+*req.DeliveryService) @@ -272,25 +276,27 @@ WHERE r.pattern = $2 // certificate and its chain in the proper order. Returns a verified // and ordered certificate and CA chain. // If the cert verification returns UnknownAuthorityError, return true to -// indicate that the certs are signed by an unknown authority (e.g. self-signed). -func verifyCertificate(certificate string, rootCA string) (string, bool, error) { +// indicate that the certs are signed by an unknown authority (e.g. self-signed). Otherwise, return false. +// If the chain returned from Certificate.Verify() does not match the input chain, +// return true. Otherwise, return false. +func verifyCertificate(certificate string, rootCA string) (string, bool, bool, error) { // decode, verify, and order certs for storage certs := strings.SplitAfter(certificate, PemCertEndMarker) if len(certs) <= 1 { - return "", false, errors.New("no certificate chain to verify") + return "", false, false, errors.New("no certificate chain to verify") } // decode and verify the server certificate block, _ := pem.Decode([]byte(certs[0])) if block == nil { - return "", false, errors.New("could not decode pem-encoded server certificate") + return "", false, false, errors.New("could not decode pem-encoded server certificate") } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return "", false, errors.New("could not parse the server certificate: " + err.Error()) + return "", false, false, errors.New("could not parse the server certificate: " + err.Error()) } if !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) { - return "", false, errors.New("no key encipherment usage for the server certificate") + return "", false, false, errors.New("no key encipherment usage for the server certificate") } bundle := "" for i := 0; i < len(certs)-1; i++ { @@ -299,7 +305,7 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, error) intermediatePool := x509.NewCertPool() if !intermediatePool.AppendCertsFromPEM([]byte(bundle)) { - return "", false, errors.New("certificate CA bundle is empty") + return "", false, false, errors.New("certificate CA bundle is empty") } opts := x509.VerifyOptions{ @@ -309,7 +315,7 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, error) // verify the certificate chain. rootPool := x509.NewCertPool() if !rootPool.AppendCertsFromPEM([]byte(rootCA)) { - return "", false, errors.New("unable to parse root CA certificate") + return "", false, false, errors.New("unable to parse root CA certificate") } opts.Roots = rootPool } @@ -317,12 +323,12 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, error) chain, err := cert.Verify(opts) if err != nil { if _, ok := err.(x509.UnknownAuthorityError); ok { - return certificate, true, nil + return certificate, true, false, nil } - return "", false, errors.New("could not verify the certificate chain: " + err.Error()) + return "", false, false, errors.New("could not verify the certificate chain: " + err.Error()) } if len(chain) < 1 { - return "", false, errors.New("can't find valid chain for cert in file in request") + return "", false, false, errors.New("can't find valid chain for cert in file in request") } pemEncodedChain := "" for _, link := range chain[0] { @@ -332,8 +338,12 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, error) } if len(pemEncodedChain) < 1 { - return "", false, errors.New("Invalid empty certicate chain in request") + return "", false, false, errors.New("Invalid empty certicate chain in request") + } + + if pemEncodedChain != certificate { + return certificate, false, true, nil } - return pemEncodedChain, false, nil + return certificate, false, false, nil } diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index 659d221814..24c11f5c5e 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -199,19 +199,19 @@ OEUjfakK71+V/HbQt477zR4k7cRbiA== func TestVerifyAndEncodeCertificate(t *testing.T) { // should fail bad base64 data - dat, _, err := verifyCertificate(BadData, "") + dat, _, _, err := verifyCertificate(BadData, "") if err == nil { t.Errorf("Unexpected result, there should have been a base64 decoding failure") } // should fail, can't verify self signed cert against this rootCA - dat, _, err = verifyCertificate(SelfSignedCertOnly, rootCA) + dat, _, _, err = verifyCertificate(SelfSignedCertOnly, rootCA) if err == nil { t.Errorf("Unexpected result, a certificate verification error should have occured") } // should pass, unknown authority is just a warning not an error - dat, unknownAuth, err := verifyCertificate(GoodTLSKeys, "") + dat, unknownAuth, _, err := verifyCertificate(GoodTLSKeys, "") if err != nil { t.Errorf("Test failure: %s", err) } @@ -220,7 +220,7 @@ func TestVerifyAndEncodeCertificate(t *testing.T) { } // should pass - dat, _, err = verifyCertificate(GoodTLSKeys, rootCA) + dat, _, _, err = verifyCertificate(GoodTLSKeys, rootCA) if err != nil { t.Errorf("Test failure: %s", err) } @@ -230,4 +230,9 @@ func TestVerifyAndEncodeCertificate(t *testing.T) { if length != 3 { // rootCA now included in certChain t.Errorf("Test failure: expected 2 certs from verifyCertificate(), got: %d ", length) } + + // certificate returned from verifyCertificate should always be the same as the input certificate + if dat != GoodTLSKeys { + t.Errorf("expected input certificate to match the output certificate") + } } From 8e267314a11fd06981e44e7bf1f26e57dc1c35ba Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 14:35:41 -0600 Subject: [PATCH 02/18] Combine PR #3382 with PR #3417 and add ECDSA support for DNS delivery services --- .../deliveryservice/keys.go | 305 +++++- .../deliveryservice/keys_test.go | 884 ++++++++++++++---- 2 files changed, 993 insertions(+), 196 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 1923d3eebd..5280b33e65 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -20,11 +20,15 @@ package deliveryservice */ import ( + "bytes" + "crypto/ecdsa" + "crypto/rsa" "crypto/x509" "database/sql" "encoding/base64" "encoding/pem" "errors" + "fmt" "net/http" "strings" @@ -59,12 +63,14 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr) return } - certChain, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertificate(req.Certificate.Crt, "") + certChain, certPrivateKey, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertKeyPair(req.Certificate.Crt, req.Certificate.Key, "") if err != nil { api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("verifying certificate: "+err.Error()), nil) return } req.Certificate.Crt = certChain + req.Certificate.Key = certPrivateKey + base64EncodeCertificate(req.Certificate) dsSSLKeys := tc.DeliveryServiceSSLKeys{ CDN: *req.CDN, @@ -279,25 +285,111 @@ WHERE r.pattern = $2 // indicate that the certs are signed by an unknown authority (e.g. self-signed). Otherwise, return false. // If the chain returned from Certificate.Verify() does not match the input chain, // return true. Otherwise, return false. -func verifyCertificate(certificate string, rootCA string) (string, bool, bool, error) { +func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA string) (string, string, bool, bool, error) { // decode, verify, and order certs for storage - certs := strings.SplitAfter(certificate, PemCertEndMarker) + var cleanPemPrivateKey string = "" + certs := strings.SplitAfter(pemCertificate, PemCertEndMarker) if len(certs) <= 1 { - return "", false, false, errors.New("no certificate chain to verify") + return "", "", false, false, errors.New("no certificate chain to verify") } // decode and verify the server certificate block, _ := pem.Decode([]byte(certs[0])) if block == nil { - return "", false, false, errors.New("could not decode pem-encoded server certificate") + return "", "", false, false, errors.New("could not decode pem-encoded server certificate") } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return "", false, false, errors.New("could not parse the server certificate: " + err.Error()) + return "", "", false, false, errors.New("could not parse the server certificate: " + err.Error()) } - if !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) { - return "", false, false, errors.New("no key encipherment usage for the server certificate") + + // validate certificate is a server auth certificate if the extension is present + if cert.Version > 1 { + serverAuthExtKeyUsageFound := false + for _, certExtKeyUsage := range cert.ExtKeyUsage { + if certExtKeyUsage == x509.ExtKeyUsageServerAuth { + serverAuthExtKeyUsageFound = true + break + } + } + + if !serverAuthExtKeyUsageFound { + return "", "", false, false, errors.New("version 3 x509 certificate does not have 'server auth' extended key usage") + } + } + + // ensure that the certificate is signed + if len(cert.Signature) == 0 { + return "", "", false, false, errors.New("certificate does not have valid signature") } + + // verify that the cert has a public key available + if cert.PublicKey == nil { + return "", "", false, false, errors.New("certificate does not have a public key") + } + + switch cert.PublicKeyAlgorithm { + case x509.RSA: + var rsaPrivateKey *rsa.PrivateKey + + // RSA is both a digital signature and encryption algorithm, hence the key encipherment + // usage must be indicated in the certificate. + // The keyUsage and extended Key Usage does not exist in version 1 of the x509 specificication. + if cert.Version > 1 && !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) { + return "", "", false, false, errors.New("no key encipherment usage indicated for the RSA server certificate") + } + + // Attempt to decode the RSA private key + rsaPrivateKey, cleanPemPrivateKey, err = decodeRSAPrivateKey(pemPrivateKey) + + // Extract the RSA public key from the x509 certificate + certPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) + if !ok || certPublicKey == nil { + return "", "", false, false, errors.New("could not get public RSA key from certificate") + } + + // Check RSA private key modulus against the x509 RSA public key modulus + if rsaPrivateKey != nil && certPublicKey != nil && !bytes.Equal(rsaPrivateKey.N.Bytes(), certPublicKey.N.Bytes()) { + return "", "", false, false, errors.New("private RSA key modulus does not match certificate RSA modulus") + } + + case x509.ECDSA: + var ecdsaPrivateKey *ecdsa.PrivateKey + + // TODO - Add DNS delivery service check here. + + // DSA and ECDSA is not an encryption algorithm and only a signing algorithm, hence the + // certificate only needs to have the DigitalSignature KeyUsage indicated. + if cert.Version > 1 && !(cert.KeyUsage&x509.KeyUsageDigitalSignature > 0) { + return "", "", false, false, errors.New("no digital signature usage indicated for the ECDSA server certificate") + } + + // Attempt to decode the ECDSA private key + ecdsaPrivateKey, cleanPemPrivateKey, err = decodeECDSAPrivateKey(pemPrivateKey) + + // Extract the ECDSA public key from the x509 certificate + certPublicKey, ok := cert.PublicKey.(*ecdsa.PublicKey) + if !ok || certPublicKey == nil { + return "", "", false, false, errors.New("could not get public ECDSA key from certificate") + } + + // Extract the ECDSA public key from the ECDSA Private Key + if strings.Compare(certPublicKey.Params().Name, ecdsaPrivateKey.Params().Name) != 0 { + return "", "", false, false, errors.New("ecdsa curve name does not match") + } + + if !bytes.Equal(certPublicKey.X.Bytes(), ecdsaPrivateKey.X.Bytes()) { + return "", "", false, false, errors.New("ecdsa public key X value mismatch") + } + + if !bytes.Equal(certPublicKey.Y.Bytes(), ecdsaPrivateKey.Y.Bytes()) { + return "", "", false, false, errors.New("ecdsa public key Y value mismatch") + } + + default: + return "", "", false, false, errors.New("certificate is signed with an unsupported PKI authentication algorithm") + } + bundle := "" for i := 0; i < len(certs)-1; i++ { bundle += certs[i] @@ -305,17 +397,18 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, bool, e intermediatePool := x509.NewCertPool() if !intermediatePool.AppendCertsFromPEM([]byte(bundle)) { - return "", false, false, errors.New("certificate CA bundle is empty") + return "", "", false, false, errors.New("certificate CA bundle is empty") } opts := x509.VerifyOptions{ Intermediates: intermediatePool, } + if rootCA != "" { // verify the certificate chain. rootPool := x509.NewCertPool() if !rootPool.AppendCertsFromPEM([]byte(rootCA)) { - return "", false, false, errors.New("unable to parse root CA certificate") + return "", "", false, false, errors.New("unable to parse root CA certificate") } opts.Roots = rootPool } @@ -323,12 +416,12 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, bool, e chain, err := cert.Verify(opts) if err != nil { if _, ok := err.(x509.UnknownAuthorityError); ok { - return certificate, true, false, nil + return pemCertificate, cleanPemPrivateKey, true, false, nil } - return "", false, false, errors.New("could not verify the certificate chain: " + err.Error()) + return "", "", false, false, errors.New("could not verify the certificate chain: " + err.Error()) } if len(chain) < 1 { - return "", false, false, errors.New("can't find valid chain for cert in file in request") + return "", "", false, false, errors.New("can't find valid chain for cert in file in request") } pemEncodedChain := "" for _, link := range chain[0] { @@ -338,12 +431,190 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, bool, e } if len(pemEncodedChain) < 1 { - return "", false, false, errors.New("Invalid empty certicate chain in request") + return "", "", false, false, errors.New("invalid empty certificate chain in request") + } + + if pemEncodedChain != pemCertificate { + return pemCertificate, cleanPemPrivateKey, false, true, nil + } + + return pemCertificate, cleanPemPrivateKey, false, false, nil +} + +// Common method to check for +func commonPrivateKeyValidation(block *pem.Block) error { + + if block == nil { + return errors.New("could not decode pem-encoded private key") + } + + // Check for encrypted keys or other unsupported key types + if strings.Contains(block.Type, "ENCRYPTED") { + return errors.New("encrypted private key not supported") + } + + // Check block headers for encryption. + for _, value := range block.Headers { + if strings.Contains(value, "ENCRYPTED") { + return errors.New("encrypted private key not supported - header: " + value) + } + } + + return nil +} + +// decode the private key +// check for proper algorithm. +// check for correct number of keys +// return private key object, cleaned private key PEM, or any errors. +func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) { + + + // Remove any white space before decoding + var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) + + // Capture all key decode errors and collapse them at the end + var decodeErrors = make([]string, 0) + + // RSA Private Key + var rsaPrivateKey *rsa.PrivateKey = nil + + // Check for proper key count before attempting to decode. + blockCount := strings.Count(trimmedPrivateKey, "\n-----END") + if blockCount < 1 { + return nil, "", errors.New("no private key PEM blocks found") + } + if blockCount > 1 { + return nil, "", errors.New("multiple private key PEM blocks found") } - if pemEncodedChain != certificate { - return certificate, false, true, nil + // Attempt to decode pem encoded text into PEM block. + block, _ := pem.Decode([]byte(trimmedPrivateKey)) + + // Check that the key was decoded and validate key isn't encrypted and + // other common validation shared between PKI algorithms + err := commonPrivateKeyValidation(block) + if err != nil { + return nil, "", err } - return certificate, false, false, nil + // Decode PKCS#8 - RSA Private Key + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + msg := fmt.Sprintf("ParsePKCS8PrivateKey error: %s", err.Error()) + decodeErrors = append(decodeErrors, msg) + } + + // Determine if the privateKey is of the correct type + rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey) + if !ok || rsaPrivateKey == nil { + msg := fmt.Sprintf("private key algorithm not supported: %T", privateKey) + decodeErrors = append(decodeErrors, msg) + } else { + return rsaPrivateKey, trimmedPrivateKey, nil + } + + // Decode PKCS#1 - RSA Private Key + rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil || rsaPrivateKey == nil { + msg := fmt.Sprintf("parsePKCS1PrivateKey error: %s", err.Error()) + decodeErrors = append(decodeErrors, msg) + return nil, "", errors.New(collapseErrors(decodeErrors)) + } + + return rsaPrivateKey, trimmedPrivateKey, nil } + + +// decode the private key +// check for proper algorithm. +// check for correct number of keys +// return private key object, cleaned private key PEM, or any errors. +func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, error) { + + // Remove any white space before decoding + var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) + + // Capture all key decode errors and collapse them at the end + var decodeErrors = make([]string, 0) + + // Check for proper key count before attempting to decode. + // ECDSA keys can have 1 or 2 PEM blocks if the 'EC PARAM' block is included. + var blockCount = strings.Count(trimmedPrivateKey, "\n-----END") + if blockCount < 1 { + return nil, "", errors.New("no EC private key PEM blocks found") + } + if blockCount > 2 { + return nil, "", errors.New("too many EC related PEM blocks found") + } + + // Attempt to decode pem encoded text into PEM block. + var pemData = []byte(trimmedPrivateKey) + for len(pemData) > 0 { + var block *pem.Block = nil + + // Check for at least one END marker + if strings.Count(string(pemData), "\n-----END") == 0 { + break + } + + block, pemData = pem.Decode(pemData) + + // Check that the key was decoded and validate key isn't encrypted and + // other common validation shared between PKI algorithms + err := commonPrivateKeyValidation(block) + if err != nil { + return nil, "", err + } + + // Check if this pem block has 'KEY' contained in the type and try to decode it. + + if strings.Contains(block.Type, "KEY") { + var ecdsaPrivateKey *ecdsa.PrivateKey + + // First try to parse an EC key the normal way, before attempting PKCS8 + ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes); + + if ecdsaPrivateKey == nil || err != nil { + msg := fmt.Sprintf("x509.ParseECPrivateKey() error: %s", err.Error()) + decodeErrors = append(decodeErrors, msg) + } else { + return ecdsaPrivateKey, trimmedPrivateKey, nil + } + + // Attempt to parse PEM block as a PKCS#8 formatted RSA Private Key. + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + + if err != nil { + msg := fmt.Sprintf("x509.ParsePKCS8PrivateKey() error: %s", err.Error()) + decodeErrors = append(decodeErrors, msg) + return nil, "", errors.New(collapseErrors(decodeErrors)) + } + + // Determine if the privateKey is of the correct type + ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) + + if !ok || ecdsaPrivateKey == nil { + msg := fmt.Sprintf("private key algorithm not supported: %T", privateKey) + decodeErrors = append(decodeErrors, msg) + return nil, "", errors.New(collapseErrors(decodeErrors)) + } + + return ecdsaPrivateKey, trimmedPrivateKey, nil + + } else if strings.Contains(block.Type, "PARAM") { + // Discard the ECDSA PARAM data + continue + } + + if block == nil { + return nil, "", errors.New("could not decode pem-encoded block") + } + } + + return nil, "", errors.New("no ECDSA private keys found") +} + +func collapseErrors(errStrings []string) string { + return fmt.Sprintf("ecdsa decode errors: [%s]", strings.Join(errStrings, ",")) +} \ No newline at end of file diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index 24c11f5c5e..e640d7584b 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -1,5 +1,10 @@ package deliveryservice +import ( + "encoding/pem" + "testing" +) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,221 +23,742 @@ package deliveryservice * specific language governing permissions and limitations * under the License. */ + +const ( + BadCertData = "This is bad cert data and it is not pem encoded" + BadKeyData = "This is bad private key data and it not pem encoeded" -import ( - "strings" - "testing" -) + PrivateKeyPKCS1RSA2048 = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEApIye2g6c0irFgoMAztPeEuV4ZX8NdORRsV2Ddi4kV9gKYiDk +xQ9eOal3Nea9kDEaUpRvk2nuVl5jbFG3sOore9Vs6YUsCvICDKCUPl5OrxURJ6BS +iC2l0jVE6FVhXf9pLX+OR8lZmMZ9GKbw1nlGGKwdF3T76gOZFSHQfT57vNFsI0Q+ +8NhWbDclNo/AnPpQuBs6ocah83BAVQk3gTRMHO3+rMLuvXVppBBqD+P5OU+LRROr +joDulub2QUPiR0Q5DczqMCjDIQB96LReryN4dx/p4x4P62SLQB6dd2vHvJNmpfl/ +CBzAdSLBRna9mSV6xw429tu5b9Z48Da5gp9igQIDAQABAoIBABoepDyS4zvNREri +RqeOJAs117WsxFMQxxLzeCGzU1uKVKOc+xN4zAk1KFIrDV4tHTOMkmWBBC87jmas +Vg9ELKDckQxEcmhOYBrnBoEb8TuDiZSTs2YgcNj8UbLbkrgcCfMJ82jbwlgo8cSP +A13YJFNYRsnpbO+JoKwlEPZAi92901MrwH5r6kf/D+q6SwLpABVvVux9UzlhKh/G +hGUcB1GhLIq1axwAtlKahkutxyUWabiTu2hGlaY8Q7JGid0t4GZHCvZ0cqQbS/bE +M2x8zskgWQrOPLneuxCYVLtpMaPdrJFSghcD39/Qw5kDiSw83m3VjrlluZG868+X +aooOOBECgYEA0YmSG09MppC2fQlmwZzbiZreygiKkrSwDvYwOwbn2z0DYwSqnJ3V +bHI0MIX4479s+1Lt3Rsr308GRIDmnx/u0gDlrAIZqh5Xoy3p2azQzCEUghr4csIp +sGEPE1FKzFL7UdQvJ3K/QeM2Xux11aF5B+jZh+2LrN3GStpZLyhyUdUCgYEAyQlK +5BzfUC6+c1Kuv6EO4YhlDy23AnTBoeGNEMOe8SQ3h4Fcz2TaOpWs2zXOLGoSoIHs +OTN5VYq3R8AQL4w75OS1Au9+nr4m0o7ix1YI3cBMwseMqQtR0OvrzOSZSm2fQZtO +SBeLPnLNg+XsR6Adxy7r2qSz9aYbXQA0WvHw9/0CgYEAxDbpJL27b3awDKKTINb8 +Ff16hwI8kWi2PSx4ua2bzIdz9nNWONbsFmNTT+UEznBhY2+i4pwhFznvCpMSYwwK +HYlNiSdmVRGYy2uhQn87/wszIyqSYRRE6a/Z6CMFwhQq19O0XGJtiwtzzKvtJCHT +Ln7zxP/C/hunJk0Vmr1rYAkCgYEAkPvCpwCrjIgpkcHvhQQCV2SmfWvasErD2ptv +wMdTuVUFNxR0ep2hRN7s6qrDJgTZqigI1LfqqWaBB53cDm50Q38tjBBsoM9B8Fhb +9KZ3fnVQ5qhDKSaguqtqQzoZ0zN7xzTaH+Pa6A6jaJxI6t7umtecAPMHVgGVelzL +ZUtXHYECgYEAyOZQ9HevD5jaWE//wXggjdASE3CFu5QkKJ1MEhEz3O9DconflKh0 +e2TVphH64nagLC8G3ta9aSHch56r4frnZ7wc6xX2sORP/PCg3iAmvEtzaevQHQue +T5BkD3zmC6RQIDOYN5DzpokgXZLuTCUl95evqAsIZ6Cd3tqNCqrJIfg= +-----END RSA PRIVATE KEY----- +` + PrivateKeyPKCS8RSA2048 = ` +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCkjJ7aDpzSKsWC +gwDO094S5Xhlfw105FGxXYN2LiRX2ApiIOTFD145qXc15r2QMRpSlG+Tae5WXmNs +Ubew6it71WzphSwK8gIMoJQ+Xk6vFREnoFKILaXSNUToVWFd/2ktf45HyVmYxn0Y +pvDWeUYYrB0XdPvqA5kVIdB9Pnu80WwjRD7w2FZsNyU2j8Cc+lC4GzqhxqHzcEBV +CTeBNEwc7f6swu69dWmkEGoP4/k5T4tFE6uOgO6W5vZBQ+JHRDkNzOowKMMhAH3o +tF6vI3h3H+njHg/rZItAHp13a8e8k2al+X8IHMB1IsFGdr2ZJXrHDjb227lv1njw +NrmCn2KBAgMBAAECggEAGh6kPJLjO81ESuJGp44kCzXXtazEUxDHEvN4IbNTW4pU +o5z7E3jMCTUoUisNXi0dM4ySZYEELzuOZqxWD0QsoNyRDERyaE5gGucGgRvxO4OJ +lJOzZiBw2PxRstuSuBwJ8wnzaNvCWCjxxI8DXdgkU1hGyels74mgrCUQ9kCL3b3T +UyvAfmvqR/8P6rpLAukAFW9W7H1TOWEqH8aEZRwHUaEsirVrHAC2UpqGS63HJRZp +uJO7aEaVpjxDskaJ3S3gZkcK9nRypBtL9sQzbHzOySBZCs48ud67EJhUu2kxo92s +kVKCFwPf39DDmQOJLDzebdWOuWW5kbzrz5dqig44EQKBgQDRiZIbT0ymkLZ9CWbB +nNuJmt7KCIqStLAO9jA7BufbPQNjBKqcndVscjQwhfjjv2z7Uu3dGyvfTwZEgOaf +H+7SAOWsAhmqHlejLenZrNDMIRSCGvhywimwYQ8TUUrMUvtR1C8ncr9B4zZe7HXV +oXkH6NmH7Yus3cZK2lkvKHJR1QKBgQDJCUrkHN9QLr5zUq6/oQ7hiGUPLbcCdMGh +4Y0Qw57xJDeHgVzPZNo6lazbNc4sahKggew5M3lVirdHwBAvjDvk5LUC736evibS +juLHVgjdwEzCx4ypC1HQ6+vM5JlKbZ9Bm05IF4s+cs2D5exHoB3HLuvapLP1phtd +ADRa8fD3/QKBgQDENukkvbtvdrAMopMg1vwV/XqHAjyRaLY9LHi5rZvMh3P2c1Y4 +1uwWY1NP5QTOcGFjb6LinCEXOe8KkxJjDAodiU2JJ2ZVEZjLa6FCfzv/CzMjKpJh +FETpr9noIwXCFCrX07RcYm2LC3PMq+0kIdMufvPE/8L+G6cmTRWavWtgCQKBgQCQ ++8KnAKuMiCmRwe+FBAJXZKZ9a9qwSsPam2/Ax1O5VQU3FHR6naFE3uzqqsMmBNmq +KAjUt+qpZoEHndwObnRDfy2MEGygz0HwWFv0pnd+dVDmqEMpJqC6q2pDOhnTM3vH +NNof49roDqNonEjq3u6a15wA8wdWAZV6XMtlS1cdgQKBgQDI5lD0d68PmNpYT//B +eCCN0BITcIW7lCQonUwSETPc70Nyid+UqHR7ZNWmEfridqAsLwbe1r1pIdyHnqvh ++udnvBzrFfaw5E/88KDeICa8S3Np69AdC55PkGQPfOYLpFAgM5g3kPOmiSBdku5M +JSX3l6+oCwhnoJ3e2o0Kqskh+A== +-----END PRIVATE KEY----- +` + PrivateKeyEncryptedRSA2048 = ` +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A6E695C7D7038524 -const ( - BadData = "This is bad data and it is not pem encoded" +YMB2rcNobMEfCRzLcGV5uSF5g1hMIuHlJjZHG0QYNpeFdP2pONtgGLH+NIVWbb7B +2dYHUbofywcJTGPigSIm0RUEHquz/+seauRXs0jvN0cEKgEyWVaQZB9yem+V5sJx +guicvKmbWfiV9u004n9G4ue9IxpWwoZp1KixOrJ7GOmRhJsNL8E9MUpJ8kD1eOIY +n8RBuo/sQMyDKinL7npk5IYE3N1tQuVAxpEn2KVXjDIIrl0SeCO5pfJdXA40Sw8Q +6bEF8GogDuEaibw2XzOfqzJsmQRks1STtCqKVnN7b7HjpY3pPgYqMqc9BVKWL3PF +a8G5BSGjjosu3SPuzIIlADlQm65O8Qi/6eZ9thByfGBtXcanSdYZtoprreEikhgC +MYnID949McXvnJTjB1snWni2FYhrWuH6iK4/7/UevFg74She5qKfwuw/YXe+p2pP +Z0ON4olUgG68/aReRoICqDurDW88zklbq8c18ECI8ppBy3tDB85Sey+ybwTliSd7 +FLBhwk/vLuhBlX6kVba8CkBUHqu8T9zECyLK2f7geDUjsw6EVXYy7whJE9LL1Sq0 +cSUpyMb5I6RXOe90zj59sBJddEsllSn2KTMhrJa2LPj+j6Df4PuwmsKdPz+DWo5r +TTAvc3iN9sZbXGjwbjiJulzapNPsfOYXrSlN9KrlkHxvmJQq0Y83ZZqmGE+Z54Z4 +TMfA/rKULJ60BSaBIwVb/NyQC+6iKUpiLDMdWhVEqKXtes7fpHnrHwHYPtTMRc6S +EG+txT5gtUKKuddBTx01UZA67L40RyC6gwbg3zipOY5XFChLQ8O4hjSaDZuQEgik +ewZhJ4ExH17+f3GaNAgPE8OtafSF86jcqt2lowrXbPi1CV9BHSriD/2G1WQycjma +Z8tFSb40fxvWHTiuDs9AyymN3OKpVX/IBm8gFxeitryxSYZ4ZOtsI7fTH+hH74C9 +ceKwu/3iPednzj1NvTpBdQvuEHRzgN/YfABXdJ71WiYRwVtE+hsdPJkKAdNYRXVs +YWJU5Ry5CAyaKZ//XsqqXM6PeACbRfWt6lqHSxnuaJuuh6dn2btJj4hX4Do81bh/ +qwKUwzIVmJCtyEaO1VsslQk7CnLZ2dErIWGnRVkeLY0wMW4qspIZUx7ikgJZZ0sz +XFMwByTkVOtzz24nX3DdhxXfClqk1wrUI50erG6XbCjbuN/XEWbKZNLKUrfxkNys +1GjCXr1qagz6s8igxAHNmK2I9N8lyZSLrqKZf6m5CjyLMHSqj95jEeXL8pw29FLs +0BQnpfuqqTQfonYDSxdHgMPZfT2y+iX5LyIaozTJuQjsDAKXhFbytrSZ9as/kmtB +ne8L04gDLiHcX3K0anLSZN/0N06LiIa9O3qygfBHdtB3iIlBnE+yuGMZGPo2KXSe +4HnU/9E6Sayh3hHEqYtDnfVtNSQhJEwGr+HgX2+wvfQYJCUX/x+2gSN40/aYQ1jI +h9gynY7NK8WybupP8JsjJ8t0UOaFwfXC2har1kq/uChOGnsBI+E+Lkx9mOPkpQ0M ++NkN+HYuZC6dqUJAUZmHdzGPgh5MPZiIwusaW7frswmKko32y9VDfg== +-----END RSA PRIVATE KEY----- +` - SelfSignedCertOnly = ` + SelfSignedRSACertificate = ` -----BEGIN CERTIFICATE----- -MIIDkjCCAnoCCQCfwd219JKpUDANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC -VVMxETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxEDAOBgNVBAoM -B0NvbWNhc3QxDjAMBgNVBAsMBXZpcGVyMRUwEwYDVQQDDAx3d3cudGVzdC5vcmcx -HjAcBgkqhkiG9w0BCQEWD21pY2tleUB0ZXN0Lm9yZzAeFw0xNzExMTYxNjM5MTNa -Fw0yNzExMTQxNjM5MTNaMIGKMQswCQYDVQQGEwJVUzERMA8GA1UECAwIQ29sb3Jh -ZG8xDzANBgNVBAcMBkRlbnZlcjEQMA4GA1UECgwHQ29tY2FzdDEOMAwGA1UECwwF -dmlwZXIxFTATBgNVBAMMDHd3dy50ZXN0Lm9yZzEeMBwGCSqGSIb3DQEJARYPbWlj -a2V5QHRlc3Qub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6m6j -iAMJpLMxZhIUE9DrPvni06NebLRah1RS8+R3J3PN1XCcgwwUZifZBpPgaSapFXbv -ZdjlrfZFpkAfgFQXlyGae6BU+n4CwNlDdgo1XbEc8qoGIds7aYHEkrQZtZyh+XFY -2BRvS6cbGGEc2x0w5IkXa136WCJcLtBzdT7FAVQJVhu9xPPnXk8igTZg6tFt27Eb -ebHCUeDArGURFiFWdXm8dGCPUVCZxSCvxuXlI15ddgfp9GbFXxCUP5VR9Pj6Btqe -7QymFROsIklpCw46ea0A87ikVMadPC21TubfayUAMQ8xl60iox5Y89g4XFrEgkyd -WxhmPWrVpVQrPDWKgwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCZZW6rln/KbGVn -UZ+7DV9PUB4r25B9wrRALy8rQw3UAePHRqZiAOVNWxrr3967zdPMc8d1kYckt+cG -G1PU5BcbUVnS2qE0Tkfvqj6r+Oickru6tKfXDaqMOEtfNanwT9uDZCTeOaiSHBzx -FpP/9TD05gEYbd1W4RRzT6/S7yLY0uYhVAHFdl2e7zOjhty4iDPF04fd+XyZ+3WS -IxSgaMrTp00maFtbpPnhTaxIGzMYtodi6FaUcOmBfMlpRGKyksN0Z3eJ6R6nhMb3 -RGJ9nuGLKvqS5u9BggcDwo1qv2k8McdSg6plK6XodLyMdBVTB6K7hwSz1uVp3mX1 -HVGE4+ou +MIIEIjCCAwqgAwIBAgIJAKfsBagyQeuuMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENv +bnRyb2wxFDASBgNVBAoMC1RyYWZmaWMgT3BzMRUwEwYDVQQLDAxVbml0IFRlc3Rp +bmcxGzAZBgNVBAMMEiouaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNzA4NDRa +Fw0zOTAzMDExNzA4NDRaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xHzAd +BgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRyb2wxFDASBgNVBAoMC1RyYWZmaWMg +T3BzMRUwEwYDVQQLDAxVbml0IFRlc3RpbmcxGzAZBgNVBAMMEiouaW52YWxpZDIu +aW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMOXU/IY3uIA +Kb0QjlWC0eEEGQAVBTOWqXclb+Ov2fZbJ+DGfrRmmBRk4Sz3H5p/l79mVDd5+Npm +UchWSut9o/lYm9zbZ6HDAyE7O9vtO7uNGq+Odg3lUzh3QSZzh+vaMeYRMzodGK+7 +6vkZ6jxGJRMazZO2LghuLH7g3ft0Dbd/QFGOQHkP/y2KeNt7jeuE4OT6jjA6OdSG ++q/gXAtFADQKkx814pEAyp1T4K59rteN2KoCbRiNrgxuewgkeu3VOGTagkwbyav1 +o3uxE+wfc3r0TOdW+2xLUO9KlaG3pioT8Vh1YcwZvghe+mkueyod1VldKl4vgH0N +sUEMpi5zB68CAwEAAaOBkjCBjzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIEMDAT +BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUJguFG8ibiS0+orhtIBPDUPAT +jL4wHwYDVR0jBBgwFoAUJguFG8ibiS0+orhtIBPDUPATjL4wHQYDVR0RBBYwFIIS +Ki5pbnZhbGlkMi5pbnZhbGlkMA0GCSqGSIb3DQEBCwUAA4IBAQB1th3ZUxczr5ZS +5Yem4KGLAAQck0o71cvmIMLXs4u0ioehM6UDxNrOwy5XaxLweZebIuUgZ44+KZU/ +UerqSinWE3zsNpHbV+7j60aFjuCKAj+9WtJVVa/A2KLPVMYaoGITgdohHeYLKqWO +6io1VvLiahXa6G1nElPhRwdBU5qnJ651I821xf9TKeIUZM+bmYyqDE2FKHbZ+hBB +AGrT265gN3/aZKi5C5s2YFZ3Oc7dlZ1ZUhZqiLeTr8cmc9bZAdNY9ppDn3xs8ThI +GQlQzUI4o2FE3OdwA28PO78/DvnZ8oVeF/KD19oExJ9tj6dzLZIrkxaRDu7CD70S +41PQLy8Q -----END CERTIFICATE----- ` - GoodTLSKeys = ` + SelfSignedRSAPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDl1PyGN7iACm9 +EI5VgtHhBBkAFQUzlql3JW/jr9n2Wyfgxn60ZpgUZOEs9x+af5e/ZlQ3efjaZlHI +VkrrfaP5WJvc22ehwwMhOzvb7Tu7jRqvjnYN5VM4d0Emc4fr2jHmETM6HRivu+r5 +Geo8RiUTGs2Tti4Ibix+4N37dA23f0BRjkB5D/8tinjbe43rhODk+o4wOjnUhvqv +4FwLRQA0CpMfNeKRAMqdU+Cufa7XjdiqAm0Yja4MbnsIJHrt1Thk2oJMG8mr9aN7 +sRPsH3N69EznVvtsS1DvSpWht6YqE/FYdWHMGb4IXvppLnsqHdVZXSpeL4B9DbFB +DKYucwevAgMBAAECggEBAIwTGVx9sUmbokizzaux58tFmv3zD+mVUcJxfkNK0kdb +myCgJ2fdPbcFVDpWtTx5elzp1RBx+uW2d4WJP1iNf1x4uA8g1oQD3H71I/ZqXOgB +swXdefCTttjulysJfGNNvYSt9sj8w4w/gZVqmNUXyz92Z5oM08TX2mf3dSK7R4OM +jk3hgGYXbgLg9ZMy3DuiZlkzIUY5sk/574j3pYaSaA+ufeIINzovod7zfqIT+5HY +nmoHKJqEjd7gZ2U0EVn3n39NXV9+eBsjuqC5aFB/oGYvH6rkXa+10vILImNoJEl2 +PRMIWggvKyG+rFn714Y5QnPwLP/So71Hq00XSMTOCUECgYEA8MVfyRuA8/d0Jyas +NZv0lbtsN1XyZ5MRsNND4DkZR4Gz3Z5JT6mXwlzTLFMl6RKxPwkxLowYGeJQnEnK +5navmcvjr9EbMrAiebmCam1PWfUKxvLVWgw4sLrscD2YlB/ylm3CugLB6p2eS5HV +7bqGhrS56PtjibZbU0dBHIc7Ek8CgYEAz/Zjw8GBV4bh9dqpKB0Kv9VF05d8maLH +X6ybRSacJ24u/icYijq1vIlz5P7fM1enVkIKF3K8V2aToMjFShnAkdWxk1Ss6UrA +DsuRq1WAf9vSIsSDao8Cl4We7M9mbnGj3pEmxdN+Fh5l9Gs09cb8v75UacDrQ3AA +x/izdR9ePKECgYA5uCdZT9WfJuBajmPUSjndN1we++Srvc8M4+iutSGBSe+znkGW +7mIqPxSE2L4K3OdO5EY9EWqpsd5/SRVyIFvCc+V2fZuWkDEDm1xPZTsTprHZtdc9 +yhZBD96kna+ZOvtt4ow/CXAxbW3IUgLGBeRAIM08tB9NoUDNexR54VVg8wKBgAhU +ZSCVIpof4/MWBAqAR0rxvu8/tRTuSTAS2NFHP5/wsN8rL7dxrI/VrZexgb0ruJ8i +3AaeaN7TU/xvrj9OksEEny04igh6HwE4tCf5r8DvTBZqap0dB0yMZJY1pHOuB5NF +mxj3ZKh8JTdKCAAELWF8vSLTQFkeJlncI0wAqqShAoGAR/iDslDHU0M/CjvqN+le +m91MxJsaFi3FZ2Pv60ghqG27X8uPbgvGXkTmmcqgAaR/Fh8b1UH+yqOnPUiremxO +oIuOOmvkBAyy0cHT/BSunqxiFOWcu9yb+2MfSWaHHxNj3kteif8Oai1lL84JOucC +/FZTue8KxnrjBcbGYYtwPCU= +-----END PRIVATE KEY----- +` + + SelfSignedNOSKIAKIRSACertificate = ` -----BEGIN CERTIFICATE----- -MIIF3DCCA8SgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAlVT -MREwDwYDVQQIDAhDb2xvcmFkbzEkMCIGA1UECgwbSXBjZG4gQ2VydGlmaWNhdGUg -QXV0aG9yaXR5MSQwIgYDVQQLDBtJcGNkbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkx -HjAcBgNVBAMMFUlwY2RuIEludGVybWVkaWF0ZSBDQTAeFw0xNzExMTYyMDUwMTla -Fw0yNjAyMDIyMDUwMTlaMHAxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFk -bzEPMA0GA1UEBwwGRGVudmVyMQ8wDQYDVQQKDAZJcGNkbiAxEjAQBgNVBAsMCUlw -Y2RuIGRldjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA1h9fXwJ17QYNMXM5jEgHecVxWm+CNPQbi2O0aLm5 -laEuoctl/xnclDgkOcV50sIgURSnaRXHCMa93zb95xQefTIvRF/1kU9e68mmFjz8 -frAdOaM90TdUf1yv26W37nT9Dx26CAiSwALXVdx+4oPorNHv20x3qPbs+3cDunAf -/XVZ+6txn9Vsg00odHZofqZbmGTvG/ybQcGPjRPaWYHaLafjpDB3wPsDDu0L0bXT -HNQ8VWzKwk8UQtzgtKxXAE2ZwLSdQWsWEKHFFNkaOqwfq21UYvct4q2rq91tDnba -fqMjNNsqVkXdR24WcP8mgV1csVNLuZhmQaBNZ6w+hGitiQIDAQABo4IBYTCCAV0w -CQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9w -ZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUiZeZ -5UmwFF1VCgpwXf3g+q1FS6MwgcMGA1UdIwSBuzCBuIAUIV7iqt3+xYa1Fx/nYzxd -1hxvNw2hgZukgZgwgZUxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEP -MA0GA1UEBwwGRGVudmVyMSQwIgYDVQQKDBtJcGNkbiBDZXJ0aWZpY2F0ZSBBdXRo -b3JpdHkxJDAiBgNVBAsMG0lwY2RuIENlcnRpZmljYXRlIGF1dGhvcml0eTEWMBQG -A1UEAwwNSXBjZG4gUm9vdCBDQYICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQM -MAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQBHX+YmO6TLbMTZByuwrgiH -uy7rPzpXTXSJvUM+upxSenrmz8H5fBzypLfKE1NOK58Rr25OyAd1IqgG1Id+8ycg -atetjI1poaNCZvKPRr48wjcTVsfgx7HXW0fykI0KT239Ok4usEM3uqmbkn7Annf7 -dby8BKz4p9n1ye7eHpipu1A5WxjBQeDymlPw/CM9E0v5F/hgiWxW+e8l5u7h43bP -1BNO6PJXJ/GONiQh4bcL0R763tNIKGVNYHSffW71vyoY6reXdKBNnk91OgjFwHTN -ALJtr9jy5xy9vKATY7gThVWDhW/uiv8LUICxxZWnCucKvhgB2bLWaHxIOr9YyjaX -hEVdHgTVXPl5cMXBw+UZLn3vw5EQHuMFAIWR2ZNIhrEvjaPon5qaEveQCDsda39w -rTr3lheyBGMhTnmA4wNV+lNSLImAc2o78aete0cTsJ619snGODUo9QO2YZ/k7vPS -mHeK0VrZvnE8uklFJUTDayLoD+SnsxztRITvk/EuRay2P1fG1/qZn7QUIg+ZM4aV -S8vPrfI9rwu8CRgxmTTtX5ZMez89fy6FlVDITjVNhRrVIc2m3xL03ASTb6NankJo -En+MLQpCFVKyQy9N72RZNz68KiPH/fraAdq4mL5NAcR4P/6Gg7Sn+qjnf/4l43zZ -+7uzqjwhdtU/YHJ9j8/cow== +MIID4DCCAsigAwIBAgIJAI84W5tsR3z4MA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENv +bnRyb2wxFDASBgNVBAoMC1RyYWZmaWMgT3BzMRUwEwYDVQQLDAxVbml0IFRlc3Rp +bmcxGzAZBgNVBAMMEiouaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNzExMTZa +Fw0zOTAzMDExNzExMTZaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xHzAd +BgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRyb2wxFDASBgNVBAoMC1RyYWZmaWMg +T3BzMRUwEwYDVQQLDAxVbml0IFRlc3RpbmcxGzAZBgNVBAMMEiouaW52YWxpZDIu +aW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2yyphDlkc0 +AmpxPAp0GZkPiGM5PgkahtafnIMCWXC5JkWz1Qk7dSgKUNl6hXg3I1dBJ/Kej461 +XwRSPNVFp1ehUsl7+D6QJy7+WEuk4Ea3s6/btMByH6+7S5EvJJGivavXlaLfqXnD +2vRKW+6EuabNpeNVplYrZQYQ2aHYIsY+HYInzqdpb/qx6BSbuvuV74N6KcI7dbpC +551y87hq2U/Mftka1TmfT/ll7bKdZ4q192ME14/USGqmyy8HHAiFvsgRjmqUUe3N +6+O0VOjjTDByL1naMw5MlSIhcIOM4O+rklAiKVzL9ONc1rz1U38JrNeUjD6pEleD +cPPBR1ge8DcCAwEAAaNRME8wDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBDAwEwYD +VR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0RBBYwFIISKi5pbnZhbGlkMi5pbnZhbGlk +MA0GCSqGSIb3DQEBCwUAA4IBAQBtkA0rtyLblXFDOntBY68gpcgaa1KjUo9YNfku +VywCVan7ZoxiJkCsirIonugJDan1Q+meMsA2tO9UXoxShXSyh6pEcqEa4uSelj1M +IysFFdtCwcUOzL3OwAY1TecC3rRadJD/hWM1F3iHPpG3BGB1LDkEZVCQdi+Gtq/C +UCHb6g1lluLt/pxHuicS4etEd1zTb1oh2CbcijMLFSGimPqkqmSBOkgO6/283xA3 +MOSm/w7yrLylq/N7/g5c6kLZSWkYpoxA5PgImJEsOwoFF9VrMzC4JPLdR3zjLq/T +wBmyIzcVFJ2g4V0iS5Ufi6uHwc7A03PVA50g7p7JUVRx5q/B -----END CERTIFICATE----- +` + SelfSignedNOSKIAKIRSAPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9ssqYQ5ZHNAJq +cTwKdBmZD4hjOT4JGobWn5yDAllwuSZFs9UJO3UoClDZeoV4NyNXQSfyno+OtV8E +UjzVRadXoVLJe/g+kCcu/lhLpOBGt7Ov27TAch+vu0uRLySRor2r15Wi36l5w9r0 +SlvuhLmmzaXjVaZWK2UGENmh2CLGPh2CJ86naW/6segUm7r7le+DeinCO3W6Qued +cvO4atlPzH7ZGtU5n0/5Ze2ynWeKtfdjBNeP1EhqpssvBxwIhb7IEY5qlFHtzevj +tFTo40wwci9Z2jMOTJUiIXCDjODvq5JQIilcy/TjXNa89VN/CazXlIw+qRJXg3Dz +wUdYHvA3AgMBAAECggEBALZkgyEV0xdRLYV0rJsMeFRPt/5XWotcQwt3WgApMSAO +FXttZkdDMOk3yfbhNBWbRlKt5iAETtmTD/HStIUHPNgn17a8iLp21gX8LZ9FvxKf +rJhI8ikbUdYgio7kug+BX0cruMdqr8PRCeRa3rueR/bWwkqr3ov5m1/Ssb5IV18t +UFj7c2nV9JMB0Wq30Awa2RcAFwC2zBkNcyZ72bR6x2DxV+QHG+xDzLO5y/PTuLEF +GBc3a9ExByC8RtUlC1n2YCwe6HSZBPALoaCIloo2isEpLpAy2ihxxaJ+tJh6iScB +t9RAvffPNN6AgRIM5qfWaoGR8E60yFBPrkHPTgCiICkCgYEA30yqVmU3zxbTvNQH +gmRCJrUW++ReLsa7xnaZmN4Pn72tGzdpmhajUWgw7LXdZ6TtHQ3UzZzt4pU5NoXa +BgE+4XKewW90GoCW66yQpg80OD0UUl5JNT/GM2cVYqROEioFg+7/rEzhF1tv2JAe ++I2uxMJoMlA82giwLJ2qDqctDZsCgYEA2XpyRHVk3GZnQ/q9tK1VyVfUkFJh0FnQ +q7uzWysi3UCOzuJYauM300LhkP5gWsB0J3osBlreNMg9MTOIy1xi7tNXdOq07Hhr +4KsP8TkDhCmQDepx1V++qVBDTlAofCO5V530Ut1+wWDBlcycAz5MIy6j5TeAWrjm +s0sisOrk35UCgYEAlQyWcn6zht6kzNj2fjmv0ih0RATGPRDYS/vkQJ6Q7T5taspN +CdZsgy054vbt53216/vMfMZwHxseCl/EDNgOAexBPbrIU9xbYMpZ7w4c/CEBDI30 +7b847By1sJcdqZA1CECiln7mjHGzMWnZ0my4KIvfgx390EeWWOGQnqFGOFsCgYBs +OEZMUq6SDlMsvMVR9z9NJeuctaH+7/KqwoiJwXlj6BAoWvHsnozVD973K93+yu4C +BwWJVAZm9Y2dwis8JwkEFx7aC0FkurfT4MvaGajqR1Rr2FI0/6P81PfpLHI48/3y +36MI6Td+OwuZ42tvIbz5dOgR1ACHJKOIbMciioDB0QKBgCtqIx4aMteQEOvXlx8E +mmD5qNBhcWUgxexqdqrvyqLScGHuhuUHny4ytTzNMulG3S8DEC2ULrq64OZuIdyT +XkhQHb96BsPSpUioe5MLzr5EnDLLV8Hptf4mmJctkd0eczgvtlX9QyFp9LpeqAMQ +FA21NyLKatm942vrWMsBGrcS +-----END PRIVATE KEY----- +` + + SelfSignedECCCertificate = ` -----BEGIN CERTIFICATE----- -MIIGBTCCA+2gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZUxCzAJBgNVBAYTAlVT -MREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwGRGVudmVyMSQwIgYDVQQKDBtJ -cGNkbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxJDAiBgNVBAsMG0lwY2RuIENlcnRp -ZmljYXRlIGF1dGhvcml0eTEWMBQGA1UEAwwNSXBjZG4gUm9vdCBDQTAeFw0xNzEx -MTYyMDM4MTVaFw0yNzExMTQyMDM4MTVaMIGMMQswCQYDVQQGEwJVUzERMA8GA1UE -CAwIQ29sb3JhZG8xJDAiBgNVBAoMG0lwY2RuIENlcnRpZmljYXRlIEF1dGhvcml0 -eTEkMCIGA1UECwwbSXBjZG4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR4wHAYDVQQD -DBVJcGNkbiBJbnRlcm1lZGlhdGUgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDKkxQ9hdMtSwfNEBqGPAKzu7CPhH+xu3kL4e+rJ09EB++fxG905mwM -Ym8s1GC/i1V1hPbOk+zLWXccZhtC49BttsDBVRmagt4q6eeD12AxzVBozWj4YnFy -ZE04CiZlAIN3qN4TnNT/O3iyvmj58QDIFVO51YNSrr7j2dQRLpoyS6s87kpw9A6T -24L1pLkmFuAgCLMFPG5HZWyZSStpXOzOc7LITZQXQzunwLazN9Z4Az8zYC9ilO6V -tNNNc+Y7MpFrTaEFFSsM2+REexuPtCOtT/ZEcOwP884T6ACcUSTv86iE/EFOPgZh -vTK2D0Nzat3ZTsc5N2vvN0eZm6COnVAvYNwrTWG4v3YUtLr/PEoFm9mtPdSA+Tsi -LkGFRjwAoAnhVieFAFulQnswbZAaJRc/xS7BJvts/3J9i7l1opqu0Ebm6L8jLeHv -p/op1TD8LIQkcp7GdsXk4LYH6VopaNOi8yoaEfKWwrXhxBdChHHlYCcfecyD8O39 -8euoGQ0zi/eaCr3MHYU1+a2+5TRPdzHx/l/3V1wxX9hmOGcrwTCtcYRzRjza2UlE -UacmwBqGyfa1Gn/iOto9yqtRvWlPGq9zJNQzNBJ6iWR7gyb0t820jpdtmFyNB5Pv -JceHyVyix/7sBUB5GwMO0iGnLPpY9Ix87nYP3itN3jkqahTrT7tHuwIDAQABo2Yw -ZDAdBgNVHQ4EFgQUIV7iqt3+xYa1Fx/nYzxd1hxvNw0wHwYDVR0jBBgwFoAUWcdI -BR6t3N8w7yUt/TOfXwmubAgwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E -BAMCAYYwDQYJKoZIhvcNAQELBQADggIBAKbd8nKA1hlxCTczTg9PHSdqHVEYWqRD -dzroOnz0KcIgJF4ncRaN3nna74wIm3nJD/WuwdF8dVbpD4YaeZKhQgmXmYggVH0l -8IIkdC3qYNTDj4xhg7qZC3pzKuNIg7yHv3Axr/rb9BvpUJxbKo/aln/G6PrbNoQx -4xb6xlK6WcYORB/UgzF6jKM5CBXaUt2QQmWts7MgnoNzZ4kxsYbuwj3rOPzHIgRY -YwJt+kh5tlyhHPkgjwUTbMg/Mv/omfzZ3+XMBD2Z69eNd9RHE9XS6AdMKtDiprhg -TLu+9tOVlydQjZk3KsqFv57/1TwKrt9JFjXk/PPQalXoP3oykoiviacd4MyiBmaW -i5WbtcxGP5vwaNn267OGlibfQmQgA1VIgDqftrQwe6T/ZwOKXqFqb56gqdW4VdOU -5bGN0uLXemriuNQolTpVmhNu0bNI5WCiY7c30XN2M5ebcBWDHOr4DOCg+mmX+tJT -Gi1jvfmA6LOYnyQ8xAV080uVe35NQ10e9my6LuXMiQ7ubvHUS5NwaQCFpLDIvbhf -2XVc46Nd0V/bolM23AQRlzuo0ISsDSeWSQVM+uQZ+pLe9G5n2MxqFd84Vu489auc -02I9cHiNahWyXPtvnvMWwImIB30CYhh5ByGWneDo3d5Zj2HAA6FwO67LlIhSe7qz -axDtcM4nO3QH +MIICiTCCAi+gAwIBAgIJAKVi77tebfBPMAoGCCqGSM49BAMCMIGFMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRy +b2wxFDASBgNVBAoMC1RyYWZmaWMgT3BzMRUwEwYDVQQLDAxVbml0IFRlc3Rpbmcx +GzAZBgNVBAMMEiouaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNzM3MjNaFw0z +OTAzMDExNzM3MjNaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xHzAdBgNV +BAcMFkFwYWNoZSBUcmFmZmljIENvbnRyb2wxFDASBgNVBAoMC1RyYWZmaWMgT3Bz +MRUwEwYDVQQLDAxVbml0IFRlc3RpbmcxGzAZBgNVBAMMEiouaW52YWxpZDIuaW52 +YWxpZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIOpnfYOa2+Fxhxl996A5cvU +OUrpY1/oy6uUdBmgo0Rfal9lv5NiMRhgg7s++jr2yf8ls2zLIosNPShIVLJl9Sej +gYUwgYIwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4E +FgQUcjdTM122v7VK7gWXexBLg+1fCu0wHwYDVR0jBBgwFoAUcjdTM122v7VK7gWX +exBLg+1fCu0wHQYDVR0RBBYwFIISKi5pbnZhbGlkMi5pbnZhbGlkMAoGCCqGSM49 +BAMCA0gAMEUCIDybXtWSTIeyETgLBGitveWAYh8dmBK/Wt3+Jdj/5GF6AiEA95I8 +96/cXDmduClIg4CnYLGbkDPsC+3nENEIr92WqgE= -----END CERTIFICATE----- +` + SelfSignedECCPrivateKey = ` +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPrjdSmSp6D/M6KBOwwz7u/NzO70nBT0U74QSCBWmwAOoAoGCCqGSM49 +AwEHoUQDQgAEg6md9g5rb4XGHGX33oDly9Q5SuljX+jLq5R0GaCjRF9qX2W/k2Ix +GGCDuz76OvbJ/yWzbMsiiw09KEhUsmX1Jw== +-----END EC PRIVATE KEY----- +` + + CASignedRSACertificateChain = ` +-----BEGIN CERTIFICATE----- +MIIE+zCCA+OgAwIBAgIFFVGJEGcwDQYJKoZIhvcNAQELBQAwga0xCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxJDAiBgNVBAMTG1Ry +YWZmaWMgT3BzIEludGVybWVkaWF0ZSBDQTEoMCYGCSqGSIb3DQEJARYZbm8tcmVw +bHlAaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNjUxMTNaFw0zOTAzMDExNjUx +MTNaMGkxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwG +RGVudmVyMRQwEgYDVQQKDAtUcmFmZmljIE9wczEgMB4GA1UEAwwXKi50ZXN0Lmlu +dmFsaWQyLmludmFsaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE +oCEYaEl1mrEOJy6jO8+QXXmlb8mYAWQL+lSOPYRvzuPWOvnfvW/BkDYpvzosfDZg +HNS106ROtWFe+kQZTTrm+xPTWMl/JIyn5ka1ZnJMAey0Oxyn2PgSmly++6esOiKH +CZm9Zhx2p7/d/fkYhu6G0X08SKVwZdtkerfKHqPEuEEcWm1H+IbMVweKDjiAqrEe +pcWKr/+i8NmOERCYvPFL6/Kf8/U4MrDM/3vh70DFKWZ3x5xWG7TWl3vCS4I+y/m7 +xEEQgF2vofcQO0CD09s4iRKCqbVM2vofWZVhYj63BgfbIXHYCFPyIpaTwc3u4fRW +pnWIUp9BFUy8PqXjh9vfAgMBAAGjggFjMIIBXzAJBgNVHRMEAjAAMBEGCWCGSAGG ++EIBAQQEAwIGQDAdBgNVHQ4EFgQU8RrF6qwRsTAtsdHUDUe//WnjNskwgdYGA1Ud +IwSBzjCBy4AUwVR9U/f9JDLi179Jc1qudzjYjhehgaukgagwgaUxCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxHDAaBgNVBAMTE1Ry +YWZmaWMgT3BzIFJvb3QgQ0ExKDAmBgkqhkiG9w0BCQEWGW5vLXJlcGx5QGludmFs +aWQyLmludmFsaWSCBRVRiRBmMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr +BgEFBQcDATAiBgNVHREEGzAZghcqLnRlc3QuaW52YWxpZDIuaW52YWxpZDANBgkq +hkiG9w0BAQsFAAOCAQEAbcOigHR11zFrPXHS7ZGG6Dro708QVrECofZJkVAKOUbZ +kWP2h4T+xSS6WEqk/1hKKo2RhiL7UlGwdtqNZ6lk9cwQORmeuIXEgy2BsbR5H4vy +L/2LhZzCSDYfeSbByhFdvLCNJMSGK+o49NUESD1zEJFPDDtMj/NLAgkLCSGi/8iF +VVJpJT3zP1I/C9Zmt8eFf6sjEdoIg6PPReJzu1hcEJLz/jqLuzoGasxea/k2k06k +Rj3GV8f3BZryN3+TKa7IiNsT7SGiZMiPWUvML/dp8aTgCNA/GlhGqzQPnDXBvgTN +JfDXiQDnR1svJZNHEfQDPIEeY6ECBAEaU0rgH9/iZg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEOTCCAyGgAwIBAgIFFVGJEGYwDQYJKoZIhvcNAQELBQAwgaUxCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxHDAaBgNVBAMTE1Ry +YWZmaWMgT3BzIFJvb3QgQ0ExKDAmBgkqhkiG9w0BCQEWGW5vLXJlcGx5QGludmFs +aWQyLmludmFsaWQwHhcNMTkwMzA2MTY1MTEwWhcNMzkwMzAxMTY1MTEwWjCBrTEL +MAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZEZW52ZXIx +FDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9wczEkMCIG +A1UEAxMbVHJhZmZpYyBPcHMgSW50ZXJtZWRpYXRlIENBMSgwJgYJKoZIhvcNAQkB +Fhluby1yZXBseUBpbnZhbGlkMi5pbnZhbGlkMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAsu3xVwphWUz/josArTjldncVgAZHVa+NVKgJpohoyJra7IgX +IpNY9dlMd4wydPc2/Y2yc6lcZ/XlfzWQS5hYsOqMoWsylC38ZeX9yminQ+Q0TFsz +EMK3v9aFV9kiFIKPh15wF1Iau1HMypN6e61rE8ThEixLU3gGLHhMvDuD+JIoIJzj +b9DvF0GU8kJr/ur4oJQDSnGiW4cg+IGsySH4y9e9NMZmwpnNprXVkP6Rr94UKAfB +KJDb683VeuuyyknwC6ZNmUYuSLIUxXi5UPbKQi20zwJkHbXui8aBMPvOIUKXSiCd +y5apfzZw22npUUbkarg6d26BU2hVjOd+6VyrqQIDAQABo2YwZDAdBgNVHQ4EFgQU +wVR9U/f9JDLi179Jc1qudzjYjhcwHwYDVR0jBBgwFoAUwYqnYixb6XZqbD7dpFMx +280Z+5YwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZI +hvcNAQELBQADggEBADiiT8vhjan43mJDv0kFS7xipePJeXbLGgAu3PocoR9qUbh+ +7Q2Zj5p1rCDaqUoUB8C5p1T3JjPxeGLQ3A9qjWP1FUhbsHTfJzcU989Q73Iomx3k +cmmQhWt+xvCpxGFmvjBpEyyIhCkgoGBUfHQFjcyrLWbaLRXOR1eF9B0YORbJmf10 +1lxg8PQ3LclCs9m4XSI2THiURDN4dFANRYqcWvg0ncej/SOXJQ+OZ5K1AJ9z/acB +GT/EpQ6YfSyxOsKVPAu3mrIxfOAqahKFJa4bgV+a5SmiENYEKYaWObAgMpO+Ud5F +kG5IVBDJicJm/kazyAs2f4NmW+8p8CKEdrB/6gI= +-----END CERTIFICATE----- +` + CASignedRSACertificateChainPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDEoCEYaEl1mrEO +Jy6jO8+QXXmlb8mYAWQL+lSOPYRvzuPWOvnfvW/BkDYpvzosfDZgHNS106ROtWFe ++kQZTTrm+xPTWMl/JIyn5ka1ZnJMAey0Oxyn2PgSmly++6esOiKHCZm9Zhx2p7/d +/fkYhu6G0X08SKVwZdtkerfKHqPEuEEcWm1H+IbMVweKDjiAqrEepcWKr/+i8NmO +ERCYvPFL6/Kf8/U4MrDM/3vh70DFKWZ3x5xWG7TWl3vCS4I+y/m7xEEQgF2vofcQ +O0CD09s4iRKCqbVM2vofWZVhYj63BgfbIXHYCFPyIpaTwc3u4fRWpnWIUp9BFUy8 +PqXjh9vfAgMBAAECggEARD43flsjs9eewATFYQ4vOjHXOJ4V39YLvUSC+GNNhejO +ltodQ5RiJ1JAGjkunaX20WDwSrNMAa1eQDKoVAfD+8sE1IOqW6B52QRJYkhOPycj +2mHxzie14e8FZZu+VD5RIYEphNzd4CjUpN2zCNo8CzrGNpgYI2yWuscE5ve/a1TT +/diQVMpnDQkOFbqAmGS70hAjcSJ1yW5nUSSXmjjlEkxOmWt4wqLUYTmrqcW5DKxv +jmxoRb1XdWzT+ryXOVX6ilvjlQVMi4k+ohvV6svFjkRiTdii16/YK9CbRaZvq8eU ++F53LF68Cv4YlX/5C4pcwyEf+I/UolDfyNE4NrY4kQKBgQDsvYpenMs80H14wd3r +O7QpaIvZe6u++nIa9Pa0n4gwsieBEHAhrvJvqln6h2mOuWL8I6cSERBVqqUD3F5w +HdNa8mStpIF+XlBmQW5UGZTqUk6KugJzIB6ZBXKOfW6g/+xaQmC0tFTzuvsV0pZ0 +X8EmsW9xbBe/+Y/zOgLXpsfgtQKBgQDUnyNz7Gaq2SldGEVMrI8eicfV8KcH0rK7 +ocUnESxL9zvNFkz9wz1t5/D4L/D3XuLAjXtKV1lUvbzVxHh46GQxvz0/5swYjL71 +rhEDqQF2t7PISxXFq9yMAg5iOxyLwBFGDcNsL6G5SdXpM/YWGo7wSwsWdYEzZULs +UZ/ZOQIqwwKBgQCfFh/NxH+utkwawexnDw/aY67Wzwxyocnb45GFf079qjpxuKIh +gHbaIxekCyscBehGl47FzUG0z59kIMo1fVVyYEDXjxyV1rsgfAev7CDt9bFh9+19 +f7AQFGEO76tP9arWXJSv2h7cSmJAH+uK+G3LmqDRD1pGX2YkhG80i5b1oQKBgQCo +GMypqJuetSObo0WekcpwxVNFVAZqC+0cpI+/DDeuM1+HC/uAoKvfSYFcZmKm39B7 +lR+FLbvFYGB7zOHGDUyxe9VLwQdY3WVXzO9MqoAqwJ+VWa9z4STzV+jRRpSR9B5z ++Quoa5v7ZmGFBnynCwY4+cthTTMBVCxtszaiQQzyiwKBgQDnJLZONi3IcsgGOuka +4qYVQl7sSIuBJ1gyZr44WjoUlykxLij59MEnAOolR86PWif6VgNfsJL4MqTkaX++ +PgH8k1z8wkIxUP94BXLfSHJyUriHMPX45T3Rr6uBrvtVujRNIHndGKDoa7P16Hzz +otCrxsW0tXSVJ1KfW1Cwb7jtHA== +-----END PRIVATE KEY----- +` + CASignedRSARootCA = ` +-----BEGIN CERTIFICATE----- +MIIENDCCAxygAwIBAgIJAKtfkOE64RynMA0GCSqGSIb3DQEBCwUAMIGlMQswCQYD +VQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZlcjEUMBIG +A1UEChMLVHJhZmZpYyBPcHMxFDASBgNVBAsTC1RyYWZmaWMgT3BzMRwwGgYDVQQD +ExNUcmFmZmljIE9wcyBSb290IENBMSgwJgYJKoZIhvcNAQkBFhluby1yZXBseUBp +bnZhbGlkMi5pbnZhbGlkMCAXDTE5MDMwNjE2NTEwN1oYDzIwNTkwMjI0MTY1MTA3 +WjCBpTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZE +ZW52ZXIxFDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9w +czEcMBoGA1UEAxMTVHJhZmZpYyBPcHMgUm9vdCBDQTEoMCYGCSqGSIb3DQEJARYZ +bm8tcmVwbHlAaW52YWxpZDIuaW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMi3d1btekZha72UWkdJvsuZenp8zNiQW7OaLLyZvLbvCncm6sNG +nZTVTkq5LZnrq2sOc04JIf7gFJc8vnJdBPEZEP5GRbWXmel4Q4qnoOcCr4/6UZ5I +1gG1JkGMsMWq83Zv/jqtjBSpIO9fQFEiv6h9jUAkzln7lfvpM892qCKZCFLh89TZ +5flSmwmNVOW5IFvUu9uFdKDBzOYaXpBXXhua3ewh9YqUtCfwBH/zz8bb3Shm9p55 +RhT0Rp4yQpFB4FwG0MxNNqjZ8BLuF9pleTcRlTrVwTLQ2sOq7HndvyyahxtSP3BF +plFrnnzmeOZjtr7RRPvG/22fHxb6lGxnXEkCAwEAAaNjMGEwHQYDVR0OBBYEFMGK +p2IsW+l2amw+3aRTMdvNGfuWMB8GA1UdIwQYMBaAFMGKp2IsW+l2amw+3aRTMdvN +GfuWMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKEMA0GCSqGSIb3DQEB +CwUAA4IBAQCRtSa8H5mwNKT1SgSjEatLMLjzYk1jpfIns6hR2X5f+D/kZkpgPX/d +4dAke1DnMIyxE43t1RJJzoi1BhFg9YvEyNU5k5L7ECuYmgU5tbmeNx2cDu4Huy5k +6ZmQ4Amh01X3JY3MFARJyRi/+CvmT+SbwdKYs8fwhPbGcLRhlUC0tvFe6JfvceH/ +18TRlcDPC51+f+WidVkWC8Er7Mydv+bmNYqEgDEJ0UQWtI/j/hxYj1wuqvUaoN2A +GcDuf0HznG/JMOtoGmMELyxJlIHCBPG1h+myLON9/XuPHlhMQcIhmqNEBBGwSdwm +1Ybc3W8sUkBAEha1Nm4SGJOz2Lfk/rAZ +-----END CERTIFICATE----- +` + + CASignedNoSkiAkiRSACertificateChain = ` -----BEGIN CERTIFICATE----- -MIIGEjCCA/qgAwIBAgIJAL2V1hnLWuzgMA0GCSqGSIb3DQEBCwUAMIGVMQswCQYD -VQQGEwJVUzERMA8GA1UECAwIQ29sb3JhZG8xDzANBgNVBAcMBkRlbnZlcjEkMCIG -A1UECgwbSXBjZG4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSQwIgYDVQQLDBtJcGNk -biBDZXJ0aWZpY2F0ZSBhdXRob3JpdHkxFjAUBgNVBAMMDUlwY2RuIFJvb3QgQ0Ew -HhcNMTcxMTE2MjAxOTI0WhcNMjcxMTE0MjAxOTI0WjCBlTELMAkGA1UEBhMCVVMx -ETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxJDAiBgNVBAoMG0lw -Y2RuIENlcnRpZmljYXRlIEF1dGhvcml0eTEkMCIGA1UECwwbSXBjZG4gQ2VydGlm -aWNhdGUgYXV0aG9yaXR5MRYwFAYDVQQDDA1JcGNkbiBSb290IENBMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2HsLknm9wx1V33zttMWn1sFEJyLNMeeW -hA0dweKChqDVw5lAyIid0lqjnjIEivlAM8zd2NAPZTHFG9BT3unduNcDcWuRgh33 -mlyssEharWtE6U7lzw8RMGWkyWQkJ2E0SxjE/VmKQjH3/4Ak8ShhTZFKEZuweRdg -j218qUemsOV+ENTsnGUxoAPpr5cGGo4igfO9tpI1g7PWnkYrVFtwsPoy2CKxqh/I -3F67EZq2yROBy9gBhC5FuZhuvgptvSakNQy/w+9buRffshb69wLsbqQayhjlLqcQ -Xkch4y6cG8Ylg+hrqzmG3vG4q03YFz8PuMd/uNxeJQAbZJ/sXh7jVQNJitgi6oOy -j1xVzNKUqb1Mx25DhBy125/l8wGBdsCRUYR6r70NAZRndjkQKV4l3tTQ4+o2rdjd -C/2Sk2/bHVbytMq4Iz+1sOsIUV3La+R+DWcLA6UonpEocNb8bt5bu4JhRDrnJwPi -4jRaH+KgxpBTIlZ3aFnSs0I3wkPOgA3DrI6LWxgt3BfPuK9DPma1rc4B1cwSQTNk -yyUY2boXsnLMMPebF3djwbtYEdqAaixxzzQCVYlhfCEQjqceSd6TJ2SdzH4I3J7x -OsLz1Lj/92aDeeq77q/c9FidnfNe75zB7gXN/bTtb55ZcTTO8XAEvegxcrw5CnO1 -MnFw6xDf++UCAwEAAaNjMGEwHQYDVR0OBBYEFFnHSAUerdzfMO8lLf0zn18JrmwI -MB8GA1UdIwQYMBaAFFnHSAUerdzfMO8lLf0zn18JrmwIMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQB+aYWZh+/gCmFy -oI582AC5+54c7xeLRmtQPmFpAA2Y4iTSeGyjv2g5M9agQ4Ixwue5DluQlsDcDsJw -lsXVHyAlCf6nDbJOpf5m6ixfvBF+QzEeXjUG74iSCWrApYFmsNsCrlsM/EPJogqu -7cgGvHwWYNjPzuwoU0AWHO9FgIbDz3Mc15ZlHIQ2T/ixxyBfpIPc5D91k4u/ZWSb -hO6lsM1iEAvv9ToUXkKttCQ0fN34BwYX47AxC71tSt9/VKIDIEXjzqJJpbJdBGSm -WuiZHWwBzVw7k5y+S+wM5vZ/OMw0thL+I53zmkxGEf3tMH4POeKvX/u19n0TFk/1 -96cztVmTB6W67mb9zZ8ySeJtD9uXE44ycxk93gTnarkIGdTf8XonCVlkHGpb6TWM -5E7aWCoVbqQRkF1rqPza8hRJGH1EGkmdbkuyUMLmQ1FJK9f/xFIcrdBGpMlxyOoL -MSeFeagoSLNq5xzjucF/6mkAUJ8UZAxrSGmaDEaSt1/qJRHovHct2b5FWZLuRt0g -fDsGoKT8IFuapSsmFEInvD0WKXDSPlU8rTy1ZBDlCqp3eNH4tCfLahk7vLA0Jbf7 -ULrtDnrNfjxUYFcF0RcauR1dlrQQRAs31QOzX+JOr4gUG7yXa3j64nx2G5MpLgSo -OEUjfakK71+V/HbQt477zR4k7cRbiA== +MIID/zCCAuegAwIBAgIFFVGJhGIwDQYJKoZIhvcNAQELBQAwga0xCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxJDAiBgNVBAMTG1Ry +YWZmaWMgT3BzIEludGVybWVkaWF0ZSBDQTEoMCYGCSqGSIb3DQEJARYZbm8tcmVw +bHlAaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxODU0MjVaFw0zOTAzMDExODU0 +MjVaMGkxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwG +RGVudmVyMRQwEgYDVQQKDAtUcmFmZmljIE9wczEgMB4GA1UEAwwXKi50ZXN0Lmlu +dmFsaWQyLmludmFsaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS +Mski1L4DVQfYdwXBxBHAWD3ZdpoS+MZa3lJXPMecpNOQfZmFzI16l3oKaePK0t2a +2BmxPmueiQ4UD4n2x3Z4bV/sjz6W13ATZs+N3EZopkr5kjr5T4NxiHaWA2JCFBFF +aMhJwoX4g94pUuHKHm5iMr7mr6nJLKwXW1RrZ3hl8q3vBoo0DzyZ1lIo+s1MqMzG +G86Wdw49lNwgi4eCMBPnX+UOENij0Kl80KfoCsp9FOxbAtZIpP5cgmb8EQnmuaoV +wbetaz2sZ+S/qasSr1nlD9wuZ74dCTxnPzt+hguyhiSLra0sd48ie9QdCqSHyYAc +rmNtELNY3ytbEN2KG0xnAgMBAAGjaTBnMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEB +BAQDAgZAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAiBgNV +HREEGzAZghcqLnRlc3QuaW52YWxpZDIuaW52YWxpZDANBgkqhkiG9w0BAQsFAAOC +AQEAHkjRjqQSsLCJUQE6QNBcx5I+hle3InFiyvr5u2DAuL95GzA4LQbk1voYFj2h +fCgAE9ON2aViPjlqQcPYl+2Koyk0vkQwkSb8oJsEucAcAGk65BmlBVDbM9IgVC96 +ILYuk0kT+Y0CgvEWBftodYs8xKEAkNuopUTKZH1iPLIFghI3cxuU56G6A4XUFEbZ +Af5qM2UBxFnKPPm7HyKs7WPoud9/V4d7UaaspXwFdvA7f8bGJvgjHGYE8XBZONgQ +YJWLBgCfIKF0LqXAFwVrbbzJEshRT+WXCNvCCq5+AJK4gBaovzk7QkAREkwTe7Du +++NBiHeG0TrPN6tX7Ke7EUYcHg== -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID+TCCAuGgAwIBAgIFFVGJhGAwDQYJKoZIhvcNAQELBQAwgaUxCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxHDAaBgNVBAMTE1Ry +YWZmaWMgT3BzIFJvb3QgQ0ExKDAmBgkqhkiG9w0BCQEWGW5vLXJlcGx5QGludmFs +aWQyLmludmFsaWQwHhcNMTkwMzA2MTg1NDIyWhcNMzkwMzAxMTg1NDIyWjCBrTEL +MAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZEZW52ZXIx +FDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9wczEkMCIG +A1UEAxMbVHJhZmZpYyBPcHMgSW50ZXJtZWRpYXRlIENBMSgwJgYJKoZIhvcNAQkB +Fhluby1yZXBseUBpbnZhbGlkMi5pbnZhbGlkMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAtkDh9gusfqgvuTN/EYfiXS/JbnX34R9Kjau3JRqA+CttbY7i +5pYbb+xdVBiUSEO2hikIF9LbuCrEQUdwPbBdX5gratDcOquqwYj47uh9ii1UEsH+ +7Sa4aV2Tr1zOFLrdkuKdJIUk1Gwp6yfoLAsXDfmScIY61EMfEcau9zH/UlCNMbfT +UMYIkJJK8iPyFlS/EehhFuPd+0Mjd/qXPCBBD0bCcJLVka/mAjKyXZPJ6Vyh4/UD +5Ne+bVp7VatiWaiAf7wCF0pOr81yTdEYV7Sp53fXMUEuwACClV88YlET3eGwfSXd +j7ugKBnyDX3TlgOZix88qRhrJro+Zr9i4RMl8wIDAQABoyYwJDASBgNVHRMBAf8E +CDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIChDANBgkqhkiG9w0BAQsFAAOCAQEAWIM+ +R69UBhumUvzLsw2xXTPmHElzuM0w5BQMfJcvZ3gsdo0wvCXkKQPSu2yPBH0BuqRt +l29Ng3+ciuvRqk+wnDp8BH651U6U7oqSw2V7alOOy4ugPdQm7NNbJuOSYCCAngEh +ohEloW/4CGLyyY4ffNfoPySgl0xXL8B/QVuTuw/0IPK448ziUJ346sZf1oBQcM2y ++gHfbNp+jQM9lQeQhjv2TKFZKrfy6uS5hHQAlpo17e0oPZA+Yw6+hQ1n91CGZ/Xx +rWm+oBTAyZUuL0NgHBCwGzZMpqKk2hyevvOC3yWQsxhbh3Q92ucxx3ifQv+WsGu5 +e8Rwmr3/doh6voOnGQ== +-----END CERTIFICATE----- +` + CASignedNoSkiAkiRSAPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSMski1L4DVQfY +dwXBxBHAWD3ZdpoS+MZa3lJXPMecpNOQfZmFzI16l3oKaePK0t2a2BmxPmueiQ4U +D4n2x3Z4bV/sjz6W13ATZs+N3EZopkr5kjr5T4NxiHaWA2JCFBFFaMhJwoX4g94p +UuHKHm5iMr7mr6nJLKwXW1RrZ3hl8q3vBoo0DzyZ1lIo+s1MqMzGG86Wdw49lNwg +i4eCMBPnX+UOENij0Kl80KfoCsp9FOxbAtZIpP5cgmb8EQnmuaoVwbetaz2sZ+S/ +qasSr1nlD9wuZ74dCTxnPzt+hguyhiSLra0sd48ie9QdCqSHyYAcrmNtELNY3ytb +EN2KG0xnAgMBAAECggEBAKyW3IXH7nin8bgwCj8OMZEgIzCSbHHVaHCmCS/uDOw2 +fiwupMayrRwSkjdIuKwJtcF1XKsm2JCkcjXQiHRjVIgPLmr7NuX94N1dVmBhlEJL +AFapVdjtC71F0jDceGpPNdsq7QF7QitKgzilABXIJNRmXE7nv14aWvcWm1tQ6w+w +1RkAEqmPcmEzGeOxWWMcaUFamEPI/SDGIDSYyeVW3qH2afqgm2B3WMU0A9hM2iDV +rTXYQpQCaTulSSCNYXCou+cOlvN+Jvf21OjxoZ0/UjGqeM42aCdyUU9K0Jc56Ps6 +RdW8rObTAYFQJj1wp9NB41QRh02HIBp7yhyyazJoXIkCgYEA8VbRqwNN7g3QmCp9 +gDxm/CQ+1tDFfbSteRnvcPwpQoLY8L+XOCws8VPP3IfKSwVU21CS+ji+0uk+x8nj +83iyFHK8K/ToAeijllftACcBgJDQOfRq9LrXwHBCIvTq4pwNoPiSVwtUotaZ5AQX +DMTOB9T6hnMu+YpaOtq84O2xHyMCgYEA3veuizIYnpi1QnTDB5zn08EWLWQYMjrq +K4SUqgL3Y81dls34bPHHAPqcK62pMRnK7qbgdJ7wjJiODC3ZZ7bjZHJFNFO7RzEA +ktFNCZ344CuX7vNR9NywathFA46mu/eCKWJLI/NrF1IclGG08ju+y8lrFm0UdxOe +9G228h30s+0CgYBHOCOvn84Djjgcb42RpkGN7vRMWFevfP4kWq76XK+gXRTAFwn9 +Haw1m1If9kKQWQZtoh19kfleLE7GjqGiW9/RgPpezmsZBRohZ9kczmX3FsUcFTDq +/6hjtb0Oq9AVB5BODIzC+ykC1OmdDEfxELLsRMGZo6wdH+L4s0xB5GL8mQKBgGMs +S6iCKc0xIz5h7PWP5tWbBqA96z08Uzf0CqPsGdl8WOpgxuS+TcOztI8A+UZrsIWi +GCgHIfuHR3dHVXH6OP5OjVWPALfTpeunyNpEN5SOD1ArTgLZvmZnt5qzcpocpvp9 +S+q7tKB0111wcClmRaEi/8zDy9yDD6qsujjK9jKpAoGAWQCY3cGmJD5tbt2FtHbb +hcAmRHPHGNps2rfW6JzQsLcb47Tp5iqt8aZYTtehnQyb7wyBdP68MGloenI6x3dQ +UjVsFHOBQq/cUVgoIlKcm9kmByjmGKcgWtPHi0lFT8u8kLvxf2NUiZyKDis+P2xq +0ojmGWKT22C4HUSsMTfq2Ew= +-----END PRIVATE KEY----- ` - rootCA = ` + CASignedNoSkiAkiRSARootCA = ` -----BEGIN CERTIFICATE----- -MIIGEjCCA/qgAwIBAgIJAL2V1hnLWuzgMA0GCSqGSIb3DQEBCwUAMIGVMQswCQYD -VQQGEwJVUzERMA8GA1UECAwIQ29sb3JhZG8xDzANBgNVBAcMBkRlbnZlcjEkMCIG -A1UECgwbSXBjZG4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSQwIgYDVQQLDBtJcGNk -biBDZXJ0aWZpY2F0ZSBhdXRob3JpdHkxFjAUBgNVBAMMDUlwY2RuIFJvb3QgQ0Ew -HhcNMTcxMTE2MjAxOTI0WhcNMjcxMTE0MjAxOTI0WjCBlTELMAkGA1UEBhMCVVMx -ETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxJDAiBgNVBAoMG0lw -Y2RuIENlcnRpZmljYXRlIEF1dGhvcml0eTEkMCIGA1UECwwbSXBjZG4gQ2VydGlm -aWNhdGUgYXV0aG9yaXR5MRYwFAYDVQQDDA1JcGNkbiBSb290IENBMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2HsLknm9wx1V33zttMWn1sFEJyLNMeeW -hA0dweKChqDVw5lAyIid0lqjnjIEivlAM8zd2NAPZTHFG9BT3unduNcDcWuRgh33 -mlyssEharWtE6U7lzw8RMGWkyWQkJ2E0SxjE/VmKQjH3/4Ak8ShhTZFKEZuweRdg -j218qUemsOV+ENTsnGUxoAPpr5cGGo4igfO9tpI1g7PWnkYrVFtwsPoy2CKxqh/I -3F67EZq2yROBy9gBhC5FuZhuvgptvSakNQy/w+9buRffshb69wLsbqQayhjlLqcQ -Xkch4y6cG8Ylg+hrqzmG3vG4q03YFz8PuMd/uNxeJQAbZJ/sXh7jVQNJitgi6oOy -j1xVzNKUqb1Mx25DhBy125/l8wGBdsCRUYR6r70NAZRndjkQKV4l3tTQ4+o2rdjd -C/2Sk2/bHVbytMq4Iz+1sOsIUV3La+R+DWcLA6UonpEocNb8bt5bu4JhRDrnJwPi -4jRaH+KgxpBTIlZ3aFnSs0I3wkPOgA3DrI6LWxgt3BfPuK9DPma1rc4B1cwSQTNk -yyUY2boXsnLMMPebF3djwbtYEdqAaixxzzQCVYlhfCEQjqceSd6TJ2SdzH4I3J7x -OsLz1Lj/92aDeeq77q/c9FidnfNe75zB7gXN/bTtb55ZcTTO8XAEvegxcrw5CnO1 -MnFw6xDf++UCAwEAAaNjMGEwHQYDVR0OBBYEFFnHSAUerdzfMO8lLf0zn18JrmwI -MB8GA1UdIwQYMBaAFFnHSAUerdzfMO8lLf0zn18JrmwIMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQB+aYWZh+/gCmFy -oI582AC5+54c7xeLRmtQPmFpAA2Y4iTSeGyjv2g5M9agQ4Ixwue5DluQlsDcDsJw -lsXVHyAlCf6nDbJOpf5m6ixfvBF+QzEeXjUG74iSCWrApYFmsNsCrlsM/EPJogqu -7cgGvHwWYNjPzuwoU0AWHO9FgIbDz3Mc15ZlHIQ2T/ixxyBfpIPc5D91k4u/ZWSb -hO6lsM1iEAvv9ToUXkKttCQ0fN34BwYX47AxC71tSt9/VKIDIEXjzqJJpbJdBGSm -WuiZHWwBzVw7k5y+S+wM5vZ/OMw0thL+I53zmkxGEf3tMH4POeKvX/u19n0TFk/1 -96cztVmTB6W67mb9zZ8ySeJtD9uXE44ycxk93gTnarkIGdTf8XonCVlkHGpb6TWM -5E7aWCoVbqQRkF1rqPza8hRJGH1EGkmdbkuyUMLmQ1FJK9f/xFIcrdBGpMlxyOoL -MSeFeagoSLNq5xzjucF/6mkAUJ8UZAxrSGmaDEaSt1/qJRHovHct2b5FWZLuRt0g -fDsGoKT8IFuapSsmFEInvD0WKXDSPlU8rTy1ZBDlCqp3eNH4tCfLahk7vLA0Jbf7 -ULrtDnrNfjxUYFcF0RcauR1dlrQQRAs31QOzX+JOr4gUG7yXa3j64nx2G5MpLgSo -OEUjfakK71+V/HbQt477zR4k7cRbiA== +MIID9DCCAtygAwIBAgIJAJSR9zIym8jSMA0GCSqGSIb3DQEBCwUAMIGlMQswCQYD +VQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZlcjEUMBIG +A1UEChMLVHJhZmZpYyBPcHMxFDASBgNVBAsTC1RyYWZmaWMgT3BzMRwwGgYDVQQD +ExNUcmFmZmljIE9wcyBSb290IENBMSgwJgYJKoZIhvcNAQkBFhluby1yZXBseUBp +bnZhbGlkMi5pbnZhbGlkMCAXDTE5MDMwNjE4NTQyMloYDzIwNTkwMjI0MTg1NDIy +WjCBpTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZE +ZW52ZXIxFDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9w +czEcMBoGA1UEAxMTVHJhZmZpYyBPcHMgUm9vdCBDQTEoMCYGCSqGSIb3DQEJARYZ +bm8tcmVwbHlAaW52YWxpZDIuaW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKSMntoOnNIqxYKDAM7T3hLleGV/DXTkUbFdg3YuJFfYCmIg5MUP +XjmpdzXmvZAxGlKUb5Np7lZeY2xRt7DqK3vVbOmFLAryAgyglD5eTq8VESegUogt +pdI1ROhVYV3/aS1/jkfJWZjGfRim8NZ5RhisHRd0++oDmRUh0H0+e7zRbCNEPvDY +Vmw3JTaPwJz6ULgbOqHGofNwQFUJN4E0TBzt/qzC7r11aaQQag/j+TlPi0UTq46A +7pbm9kFD4kdEOQ3M6jAowyEAfei0Xq8jeHcf6eMeD+tki0AenXdrx7yTZqX5fwgc +wHUiwUZ2vZklescONvbbuW/WePA2uYKfYoECAwEAAaMjMCEwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAAO2gylryjq2 +Ou+mm4E8On/Ecchci1FUlc8ZLAzxxTdtJDZQd4b6uEEOFnXyIDy1DU3CND3ieIa0 +EL12/dsGzzhI0mJEf+oes4aaa4l0znMA7WQ58CUdBWuGoGvUzLkE3TAFqLwKC79h +DARQQp0VaM01pZQd/Sh/3+V3ijEg3818VtTvKHm5t26ggIRhSSGMhEeqCoG+9EKL +igzzaBprKzbSuGpj9QKLO4P4vIvgt2RutfqYBNR6sdzKmQYyPCYshfsoQVWo9mmD +/LLpNoSwwXGgBhI7cprp0CsN5f5/mL2dDSQqEAOl8YitVa4nL44iFrL8d4d8OM7z +jI///X8MUJs= -----END CERTIFICATE----- ` + + CASignedECCCertificateChain = `` + CASignedECCCertificateChainPrivateKey = `` + CASignedECCRootCA = `` + + CASignedNoSkiAkiECCCertificateChain = `` + CASignedNoSkiAkiECCCertificateChainPrivateKey = `` + CASignedNoSkiAkiECCRootCA = `` ) -func TestVerifyAndEncodeCertificate(t *testing.T) { +func TestDecodePrivateKeyPKCS8RSA2048(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS8RSA2048) + + if err != nil { + t.Errorf("Unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Error("can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + if privateKey == nil { + t.Error("RSA private key is nil. expect: not nil") + t.FailNow() + } +} + +func TestDecodePrivateKeyPKCS1RSA2048(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS1RSA2048) + + if err != nil { + t.Errorf("Unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Error("can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + if privateKey == nil { + t.Error("RSA private key is nil") + t.FailNow() + } +} +func TestDecodePrivateKeyBadData(t *testing.T) { + + // Expected to fail. + privateKey, _, err := decodeRSAPrivateKey(BadKeyData) + if err == nil && privateKey != nil { + t.Error("unexpected result: decoding of bad private key data should have returned an error") + t.FailNow() + } +} + +func TestDecodePrivateKeyRSAEncrypted(t *testing.T) { + + // Expected to fail on decode of encrypted pem private key + privateKey, _, err := decodeRSAPrivateKey(PrivateKeyEncryptedRSA2048) + if err == nil && privateKey != nil { + t.Error("unexpected result: decoding of encrypted private key should have returned an error") + t.FailNow() + } +} + +func TestVerifyAndEncodeCertificateBadData(t *testing.T) { // should fail bad base64 data - dat, _, _, err := verifyCertificate(BadData, "") + _, _, _, _, err := verifyCertKeyPair(BadCertData, BadKeyData, "") if err == nil { - t.Errorf("Unexpected result, there should have been a base64 decoding failure") + t.Errorf("Unexpected result: there should have been a base64 decoding failure") + } +} + +func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { + + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "") + + if err != nil { + t.Errorf("Unexpected result: a certificate verification error should have occured") } - // should fail, can't verify self signed cert against this rootCA - dat, _, _, err = verifyCertificate(SelfSignedCertOnly, rootCA) - if err == nil { + if !unknownAuth { + t.Errorf("Unexpected result: certificate verification should have detected unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Error("unexpected result: can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + + if len(certChain) == 0 { + t.Error("unexpected: certChain should not be empty") + } +} + +func TestVerifyAndEncodeCertificateSelfSignedCertKeyPair(t *testing.T) { + + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedRSACertificate, SelfSignedRSAPrivateKey, "") + + if err != nil { t.Errorf("Unexpected result, a certificate verification error should have occured") } - // should pass, unknown authority is just a warning not an error - dat, unknownAuth, _, err := verifyCertificate(GoodTLSKeys, "") + if !unknownAuth { + t.Errorf("Unexpected result, certificate verification should have detected unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Error("unexpected result: can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + if len(certChain) == 0 { + t.Error("unexpected: certchain should not empty") + } + +} + +func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t *testing.T) { + + // Should fail on cert/private-key mismatch + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificate, PrivateKeyPKCS1RSA2048, "") + + if err == nil { + t.Errorf("Unexpected result, a certificate/key modulus mismatch error should have occurred") + } +} + +func TestVerifyAndEncodeCertificateCASignedCertKeyPair(t *testing.T) { + + // Should succeed, but with unknown authority warning. + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, "") + + if err != nil { + t.Errorf("Unexpected result: " + err.Error()) + } + + if !unknownAuth { + t.Errorf("Unexpected result, certificate verification should have detected unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Error("unexpected result: can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + if len(certChain) == 0 { + t.Error("unexpected: certchain should not empty") + } +} + +func TestVerifyAndEncodeCertificateCASignedCertKeyPairWithRootCA(t *testing.T) { + + // should succeed and be fully validated. + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, CASignedRSARootCA) + if err != nil { - t.Errorf("Test failure: %s", err) + t.Errorf("Unexpected result: " + err.Error()) } + + if unknownAuth { + t.Errorf("Unexpected result: warning for unknown authority even though rootCA is in certChain") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Error("unexpected result: can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + if len(certChain) == 0 { + t.Error("unexpected: certchain should not empty") + } +} + +func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPair(t *testing.T) { + + // Should succeed, but with unknown authority warning. + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, "") + + if err != nil { + t.Errorf("Unexpected result: " + err.Error()) + } + if !unknownAuth { t.Errorf("Unexpected result, certificate verification should have detected unknown authority") } - // should pass - dat, _, _, err = verifyCertificate(GoodTLSKeys, rootCA) + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Error("unexpected result: can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + if len(certChain) == 0 { + t.Error("unexpected: certchain should not empty") + } +} + +func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *testing.T) { + + // should succeed and be fully validated despite not having subject/authority key identifier(s). + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, CASignedNoSkiAkiRSARootCA) + if err != nil { - t.Errorf("Test failure: %s", err) + t.Errorf("Unexpected result: " + err.Error()) } - certs := strings.SplitAfter(dat, PemCertEndMarker) - length := len(certs) - 1 - if length != 3 { // rootCA now included in certChain - t.Errorf("Test failure: expected 2 certs from verifyCertificate(), got: %d ", length) + if unknownAuth { + t.Errorf("Unexpected result: warning for unknown authority even though rootCA is in certChain") } - // certificate returned from verifyCertificate should always be the same as the input certificate - if dat != GoodTLSKeys { - t.Errorf("expected input certificate to match the output certificate") + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Error("unexpected result: can't decode cleaned private key pem block") + t.FailNow() + } else if len(remain) > 0 { + t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") + t.FailNow() + } + + if len(certChain) == 0 { + t.Error("unexpected: certchain should not empty") } } + + +func TestVerifyAndEncodeCertificateECCCertificateKeyPair(t *testing.T) { + // Should fail due to unsupported private/public key algorithm + _, _, _, _, err := verifyCertKeyPair(SelfSignedECCCertificate, SelfSignedECCPrivateKey, "") + + if err == nil { + t.Errorf("Unexpected result, cert/key PKI algorithm for ECC is unsupported.") + } +} \ No newline at end of file From d3162c039532b5df5965e3114933738d143ce85f Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 20:50:29 -0600 Subject: [PATCH 03/18] Update unit tests to fail faster --- .../deliveryservice/keys_test.go | 108 +++++++----------- 1 file changed, 43 insertions(+), 65 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index e640d7584b..da54d32097 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -498,22 +498,19 @@ func TestDecodePrivateKeyPKCS8RSA2048(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS8RSA2048) if err != nil { - t.Errorf("Unexpected result: " + err.Error()) + t.Fatalf("Unexpected result: " + err.Error()) } pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) if pBlock == nil { - t.Error("can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("remaining bytes after decode > 0. expected: 0") } if privateKey == nil { - t.Error("RSA private key is nil. expect: not nil") - t.FailNow() + t.Fatal("RSA private key is nil. expect: not nil") } } @@ -522,22 +519,19 @@ func TestDecodePrivateKeyPKCS1RSA2048(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS1RSA2048) if err != nil { - t.Errorf("Unexpected result: " + err.Error()) + t.Fatalf("Unexpected result: " + err.Error()) } pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) if pBlock == nil { - t.Error("can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("remaining bytes after decode > 0. expected: 0") } if privateKey == nil { - t.Error("RSA private key is nil") - t.FailNow() + t.Fatal("RSA private key is nil") } } @@ -546,8 +540,7 @@ func TestDecodePrivateKeyBadData(t *testing.T) { // Expected to fail. privateKey, _, err := decodeRSAPrivateKey(BadKeyData) if err == nil && privateKey != nil { - t.Error("unexpected result: decoding of bad private key data should have returned an error") - t.FailNow() + t.Fatal("unexpected result: decoding of bad private key data should have returned an error") } } @@ -556,8 +549,7 @@ func TestDecodePrivateKeyRSAEncrypted(t *testing.T) { // Expected to fail on decode of encrypted pem private key privateKey, _, err := decodeRSAPrivateKey(PrivateKeyEncryptedRSA2048) if err == nil && privateKey != nil { - t.Error("unexpected result: decoding of encrypted private key should have returned an error") - t.FailNow() + t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") } } @@ -565,7 +557,7 @@ func TestVerifyAndEncodeCertificateBadData(t *testing.T) { // should fail bad base64 data _, _, _, _, err := verifyCertKeyPair(BadCertData, BadKeyData, "") if err == nil { - t.Errorf("Unexpected result: there should have been a base64 decoding failure") + t.Fatalf("Unexpected result: there should have been a base64 decoding failure") } } @@ -574,27 +566,24 @@ func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "") if err != nil { - t.Errorf("Unexpected result: a certificate verification error should have occured") + t.Fatalf("Unexpected result: a certificate verification error should have occured") } if !unknownAuth { - t.Errorf("Unexpected result: certificate verification should have detected unknown authority") + t.Fatalf("Unexpected result: certificate verification should have detected unknown authority") } // Decode the clean Private Key pBlock, remain := pem.Decode([]byte(certPrivateKey)) if pBlock == nil { - t.Error("unexpected result: can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("unexpected result: can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") } - if len(certChain) == 0 { - t.Error("unexpected: certChain should not be empty") + t.Fatal("unexpected: certChain should not be empty") } } @@ -603,28 +592,25 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedRSACertificate, SelfSignedRSAPrivateKey, "") if err != nil { - t.Errorf("Unexpected result, a certificate verification error should have occured") + t.Fatalf("Unexpected result, a certificate verification error should have occured") } if !unknownAuth { - t.Errorf("Unexpected result, certificate verification should have detected unknown authority") + t.Fatalf("Unexpected result, certificate verification should have detected unknown authority") } // Decode the clean Private Key pBlock, remain := pem.Decode([]byte(certPrivateKey)) if pBlock == nil { - t.Error("unexpected result: can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("unexpected result: can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") } if len(certChain) == 0 { - t.Error("unexpected: certchain should not empty") + t.Fatal("unexpected: certchain should not empty") } - } func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t *testing.T) { @@ -633,7 +619,7 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t * _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificate, PrivateKeyPKCS1RSA2048, "") if err == nil { - t.Errorf("Unexpected result, a certificate/key modulus mismatch error should have occurred") + t.Fatalf("Unexpected result, a certificate/key modulus mismatch error should have occurred") } } @@ -643,26 +629,24 @@ func TestVerifyAndEncodeCertificateCASignedCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, "") if err != nil { - t.Errorf("Unexpected result: " + err.Error()) + t.Fatalf("Unexpected result: " + err.Error()) } if !unknownAuth { - t.Errorf("Unexpected result, certificate verification should have detected unknown authority") + t.Fatalf("Unexpected result, certificate verification should have detected unknown authority") } // Decode the clean Private Key pBlock, remain := pem.Decode([]byte(certPrivateKey)) if pBlock == nil { - t.Error("unexpected result: can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("unexpected result: can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") } if len(certChain) == 0 { - t.Error("unexpected: certchain should not empty") + t.Fatal("unexpected: certchain should not empty") } } @@ -672,26 +656,24 @@ func TestVerifyAndEncodeCertificateCASignedCertKeyPairWithRootCA(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, CASignedRSARootCA) if err != nil { - t.Errorf("Unexpected result: " + err.Error()) + t.Fatalf("Unexpected result: " + err.Error()) } if unknownAuth { - t.Errorf("Unexpected result: warning for unknown authority even though rootCA is in certChain") + t.Fatalf("Unexpected result: warning for unknown authority even though rootCA is in certChain") } // Decode the clean Private Key pBlock, remain := pem.Decode([]byte(certPrivateKey)) if pBlock == nil { - t.Error("unexpected result: can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("unexpected result: can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") } if len(certChain) == 0 { - t.Error("unexpected: certchain should not empty") + t.Fatal("unexpected: certchain should not empty") } } @@ -701,26 +683,24 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, "") if err != nil { - t.Errorf("Unexpected result: " + err.Error()) + t.Fatalf("Unexpected result: " + err.Error()) } if !unknownAuth { - t.Errorf("Unexpected result, certificate verification should have detected unknown authority") + t.Fatalf("Unexpected result, certificate verification should have detected unknown authority") } // Decode the clean Private Key pBlock, remain := pem.Decode([]byte(certPrivateKey)) if pBlock == nil { - t.Error("unexpected result: can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("unexpected result: can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") } if len(certChain) == 0 { - t.Error("unexpected: certchain should not empty") + t.Fatal("unexpected: certchain should not empty") } } @@ -730,26 +710,24 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *test certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, CASignedNoSkiAkiRSARootCA) if err != nil { - t.Errorf("Unexpected result: " + err.Error()) + t.Fatalf("Unexpected result: " + err.Error()) } if unknownAuth { - t.Errorf("Unexpected result: warning for unknown authority even though rootCA is in certChain") + t.Fatalf("Unexpected result: warning for unknown authority even though rootCA is in certChain") } // Decode the clean Private Key pBlock, remain := pem.Decode([]byte(certPrivateKey)) if pBlock == nil { - t.Error("unexpected result: can't decode cleaned private key pem block") - t.FailNow() + t.Fatal("unexpected result: can't decode cleaned private key pem block") } else if len(remain) > 0 { - t.Error("unexpected result: remaining bytes after decode > 0. expected: 0") - t.FailNow() + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") } if len(certChain) == 0 { - t.Error("unexpected: certchain should not empty") + t.Fatal("unexpected: certchain should not empty") } } @@ -759,6 +737,6 @@ func TestVerifyAndEncodeCertificateECCCertificateKeyPair(t *testing.T) { _, _, _, _, err := verifyCertKeyPair(SelfSignedECCCertificate, SelfSignedECCPrivateKey, "") if err == nil { - t.Errorf("Unexpected result, cert/key PKI algorithm for ECC is unsupported.") + t.Fatalf("Unexpected result, cert/key PKI algorithm for ECC is unsupported.") } } \ No newline at end of file From d8d902c50679c3e3459a6576fd21bc2e75faafb9 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 21:13:26 -0600 Subject: [PATCH 04/18] Update comments related to RSA/ECDSA key mismatch verification --- .../traffic_ops_golang/deliveryservice/keys.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 5280b33e65..35575b8834 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -373,19 +373,24 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin return "", "", false, false, errors.New("could not get public ECDSA key from certificate") } - // Extract the ECDSA public key from the ECDSA Private Key + // Compare the ECDSA curve name contained within the x509.PublicKey against the curve name indicated in the private key if strings.Compare(certPublicKey.Params().Name, ecdsaPrivateKey.Params().Name) != 0 { return "", "", false, false, errors.New("ecdsa curve name does not match") } + // Verify that ECDSA public value X matches in both the cert.PublicKey and the private key. if !bytes.Equal(certPublicKey.X.Bytes(), ecdsaPrivateKey.X.Bytes()) { return "", "", false, false, errors.New("ecdsa public key X value mismatch") } + // Verify that ECDSA public value Y matches in both the cert.PublicKey and the private key. if !bytes.Equal(certPublicKey.Y.Bytes(), ecdsaPrivateKey.Y.Bytes()) { return "", "", false, false, errors.New("ecdsa public key Y value mismatch") } + case x509.DSA: + return "", "", false, false, errors.New("certificate is signed with unsupported DSA PKI algorithm") + default: return "", "", false, false, errors.New("certificate is signed with an unsupported PKI authentication algorithm") } @@ -441,7 +446,8 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin return pemCertificate, cleanPemPrivateKey, false, false, nil } -// Common method to check for +// Common privateKey validation logic. +// Reject unsupported encrypted private keys func commonPrivateKeyValidation(block *pem.Block) error { if block == nil { @@ -469,7 +475,6 @@ func commonPrivateKeyValidation(block *pem.Block) error { // return private key object, cleaned private key PEM, or any errors. func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) { - // Remove any white space before decoding var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) @@ -541,9 +546,11 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // Check for proper key count before attempting to decode. // ECDSA keys can have 1 or 2 PEM blocks if the 'EC PARAM' block is included. var blockCount = strings.Count(trimmedPrivateKey, "\n-----END") + if blockCount < 1 { return nil, "", errors.New("no EC private key PEM blocks found") } + if blockCount > 2 { return nil, "", errors.New("too many EC related PEM blocks found") } @@ -568,7 +575,6 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err } // Check if this pem block has 'KEY' contained in the type and try to decode it. - if strings.Contains(block.Type, "KEY") { var ecdsaPrivateKey *ecdsa.PrivateKey @@ -577,7 +583,7 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err if ecdsaPrivateKey == nil || err != nil { msg := fmt.Sprintf("x509.ParseECPrivateKey() error: %s", err.Error()) - decodeErrors = append(decodeErrors, msg) + decodeErrors = append(decodeErrors, msg) } else { return ecdsaPrivateKey, trimmedPrivateKey, nil } From 303581a9bed4847a8c2d5df932e7deaf04d16f09 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 21:22:35 -0600 Subject: [PATCH 05/18] Make decoding ECDSA PEM blocks more readable --- .../deliveryservice/keys.go | 70 +++++++++---------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 35575b8834..2313bb0907 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -506,7 +506,7 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Decode PKCS#8 - RSA Private Key privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - msg := fmt.Sprintf("ParsePKCS8PrivateKey error: %s", err.Error()) + msg := fmt.Sprintf("parse pkcs#8 error: %s", err.Error()) decodeErrors = append(decodeErrors, msg) } @@ -522,7 +522,7 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Decode PKCS#1 - RSA Private Key rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil || rsaPrivateKey == nil { - msg := fmt.Sprintf("parsePKCS1PrivateKey error: %s", err.Error()) + msg := fmt.Sprintf("parse pkcs#1 error: %s", err.Error()) decodeErrors = append(decodeErrors, msg) return nil, "", errors.New(collapseErrors(decodeErrors)) } @@ -537,6 +537,8 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // return private key object, cleaned private key PEM, or any errors. func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, error) { + var ecdsaPrivateKey *ecdsa.PrivateKey = nil + // Remove any white space before decoding var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) @@ -567,6 +569,10 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err block, pemData = pem.Decode(pemData) + if block == nil { + return nil, "", errors.New("could not decode pem-encoded block") + } + // Check that the key was decoded and validate key isn't encrypted and // other common validation shared between PKI algorithms err := commonPrivateKeyValidation(block) @@ -575,47 +581,35 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err } // Check if this pem block has 'KEY' contained in the type and try to decode it. - if strings.Contains(block.Type, "KEY") { - var ecdsaPrivateKey *ecdsa.PrivateKey - - // First try to parse an EC key the normal way, before attempting PKCS8 - ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes); - - if ecdsaPrivateKey == nil || err != nil { - msg := fmt.Sprintf("x509.ParseECPrivateKey() error: %s", err.Error()) - decodeErrors = append(decodeErrors, msg) - } else { - return ecdsaPrivateKey, trimmedPrivateKey, nil - } - - // Attempt to parse PEM block as a PKCS#8 formatted RSA Private Key. - privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) - - if err != nil { - msg := fmt.Sprintf("x509.ParsePKCS8PrivateKey() error: %s", err.Error()) - decodeErrors = append(decodeErrors, msg) - return nil, "", errors.New(collapseErrors(decodeErrors)) - } - - // Determine if the privateKey is of the correct type - ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) - - if !ok || ecdsaPrivateKey == nil { - msg := fmt.Sprintf("private key algorithm not supported: %T", privateKey) - decodeErrors = append(decodeErrors, msg) - return nil, "", errors.New(collapseErrors(decodeErrors)) - } + if !strings.Contains(block.Type, "KEY") { + continue + } + // First try to parse an EC key the normal way, before attempting PKCS8 + ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes); + if ecdsaPrivateKey == nil || err != nil { + msg := fmt.Sprintf("x509.ParseECPrivateKey() error: %s", err.Error()) + decodeErrors = append(decodeErrors, msg) + } else { return ecdsaPrivateKey, trimmedPrivateKey, nil - - } else if strings.Contains(block.Type, "PARAM") { - // Discard the ECDSA PARAM data - continue } - if block == nil { - return nil, "", errors.New("could not decode pem-encoded block") + // Second, try to parse PEM block as a PKCS#8 formatted RSA Private Key. + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + msg := fmt.Sprintf("x509.ParsePKCS8PrivateKey() error: %s", err.Error()) + decodeErrors = append(decodeErrors, msg) + return nil, "", errors.New(collapseErrors(decodeErrors)) } + // Make sure the privateKey is of the correct type (ecdsa.PrivateKey) + ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) + if !ok || ecdsaPrivateKey == nil { + msg := fmt.Sprintf("private key algorithm not supported: %T", privateKey) + decodeErrors = append(decodeErrors, msg) + return nil, "", errors.New(collapseErrors(decodeErrors)) + } + + return ecdsaPrivateKey, trimmedPrivateKey, nil } return nil, "", errors.New("no ECDSA private keys found") From f6aa5e0023e1bd5151a3aa4448be88525902ad20 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 22:04:17 -0600 Subject: [PATCH 06/18] Add Unit tests for ECDSA privateKey decoding with and without param pem block --- .../deliveryservice/keys_test.go | 155 +++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index da54d32097..b02d785f68 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -2,6 +2,7 @@ package deliveryservice import ( "encoding/pem" + "strings" "testing" ) @@ -86,6 +87,42 @@ eCCN0BITcIW7lCQonUwSETPc70Nyid+UqHR7ZNWmEfridqAsLwbe1r1pIdyHnqvh +udnvBzrFfaw5E/88KDeICa8S3Np69AdC55PkGQPfOYLpFAgM5g3kPOmiSBdku5M JSX3l6+oCwhnoJ3e2o0Kqskh+A== -----END PRIVATE KEY----- +` + PrivateKeyECCNISTPrime256V1 = ` +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIM1u5X+fmuna0jK5NoBO8CRWJiTzopg9xzqjs34dB3osoAoGCCqGSM49 +AwEHoUQDQgAEq0gH7B1q2cWMDvYTmFr+xNmbrJBMK9ERmZkSfRfaDmzxqvE56FrB +p3aue/xDiaFp9yniuM8lqbTWHwyopraMlA== +-----END EC PRIVATE KEY----- +` + PrivateKeyECCNISTPrime256V1WithoutParams = ` +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIM1u5X+fmuna0jK5NoBO8CRWJiTzopg9xzqjs34dB3osoAoGCCqGSM49 +AwEHoUQDQgAEq0gH7B1q2cWMDvYTmFr+xNmbrJBMK9ERmZkSfRfaDmzxqvE56FrB +p3aue/xDiaFp9yniuM8lqbTWHwyopraMlA== +-----END EC PRIVATE KEY----- +` + PrivateKeyECCNISTSecP384R1 = ` +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDB563eEBAdLcLBpgUi3WOszJS6JOHkAcAePAWX/fvguKP56brbIsZnl +/IlujyM6RACgBwYFK4EEACKhZANiAAStW0BfZ2KCkmBQv9Cc8GT9hoGDRuJvfbj0 +cmgIRz1yhqHy1Psw3/z8FhhBkhm1Y0InJ7xxt0CsOYs2/faAOmNcKt3mwwthLcEy +9XVZrwbog5s76datlz/7iVd4Jo7vS88= +-----END EC PRIVATE KEY----- +` + PrivateKeyECCNISTSecP384R1WithoutParams = ` +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDB563eEBAdLcLBpgUi3WOszJS6JOHkAcAePAWX/fvguKP56brbIsZnl +/IlujyM6RACgBwYFK4EEACKhZANiAAStW0BfZ2KCkmBQv9Cc8GT9hoGDRuJvfbj0 +cmgIRz1yhqHy1Psw3/z8FhhBkhm1Y0InJ7xxt0CsOYs2/faAOmNcKt3mwwthLcEy +9XVZrwbog5s76datlz/7iVd4Jo7vS88= +-----END EC PRIVATE KEY----- ` PrivateKeyEncryptedRSA2048 = ` -----BEGIN RSA PRIVATE KEY----- @@ -535,6 +572,122 @@ func TestDecodePrivateKeyPKCS1RSA2048(t *testing.T) { } } +func TestDecodePrivateKeyECCNISTPrime256V1(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTPrime256V1) + + if err != nil { + t.Fatalf("Unexpected result: " + err.Error()) + } + + var pemData = []byte(cleanPemPrivateKey) + var parsedBlocks = make([]*pem.Block, 0) + + for len(pemData) > 0 { + var block *pem.Block = nil + + // Check for at least one END marker + if strings.Count(string(pemData), "\n-----END") == 0 { + break + } + + block, pemData = pem.Decode(pemData) + + if block == nil { + t.Fatal("can't decode cleaned ecdsa private-key/param pem block") + } + + parsedBlocks = append(parsedBlocks, block) + } + + expectedParsedBlocks := 2 + if len(parsedBlocks) != expectedParsedBlocks { + t.Fatalf("incorrect number of parsed pem blocks - expected:%d actual:%d", expectedParsedBlocks, len(parsedBlocks)) + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + +func TestDecodePrivateKeyECCNISTPrime256V1WithoutParams(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTPrime256V1WithoutParams) + + if err != nil { + t.Fatalf("Unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Fatal("can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("remaining bytes after decode > 0. expected: 0") + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + +func TestDecodePrivateKeyECCNISTSecP384R1(t *testing.T) { + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTSecP384R1) + + if err != nil { + t.Fatalf("Unexpected result: " + err.Error()) + } + + var pemData = []byte(cleanPemPrivateKey) + var parsedBlocks = make([]*pem.Block, 0) + + for len(pemData) > 0 { + var block *pem.Block = nil + + // Check for at least one END marker + if strings.Count(string(pemData), "\n-----END") == 0 { + break + } + + block, pemData = pem.Decode(pemData) + + if block == nil { + t.Fatal("can't decode cleaned ecdsa private-key/param pem block") + } + + parsedBlocks = append(parsedBlocks, block) + } + + expectedParsedBlocks := 2 + if len(parsedBlocks) != expectedParsedBlocks { + t.Fatalf("incorrect number of parsed pem blocks - expected:%d actual:%d", expectedParsedBlocks, len(parsedBlocks)) + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + +func TestDecodePrivateKeyECCNISTSecP384R1WithoutParams(t *testing.T) { + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTSecP384R1WithoutParams) + + if err != nil { + t.Fatalf("Unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Fatal("can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("remaining bytes after decode > 0. expected: 0") + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + func TestDecodePrivateKeyBadData(t *testing.T) { // Expected to fail. @@ -739,4 +892,4 @@ func TestVerifyAndEncodeCertificateECCCertificateKeyPair(t *testing.T) { if err == nil { t.Fatalf("Unexpected result, cert/key PKI algorithm for ECC is unsupported.") } -} \ No newline at end of file +} From 0b0d877202f0c6f285eb124aa892faaaf97cb19b Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 22:38:44 -0600 Subject: [PATCH 07/18] Rename Unit test methods. Add unit test for encrypted ECDSA private key --- .../deliveryservice/keys_test.go | 133 ++++++++++-------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index b02d785f68..e92b592d63 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -24,10 +24,10 @@ import ( * specific language governing permissions and limitations * under the License. */ - + const ( BadCertData = "This is bad cert data and it is not pem encoded" - BadKeyData = "This is bad private key data and it not pem encoeded" + BadKeyData = "This is bad private key data and it is not pem encoded" PrivateKeyPKCS1RSA2048 = ` -----BEGIN RSA PRIVATE KEY----- @@ -88,7 +88,39 @@ eCCN0BITcIW7lCQonUwSETPc70Nyid+UqHR7ZNWmEfridqAsLwbe1r1pIdyHnqvh JSX3l6+oCwhnoJ3e2o0Kqskh+A== -----END PRIVATE KEY----- ` - PrivateKeyECCNISTPrime256V1 = ` + PrivateKeyEncryptedRSA2048 = ` +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A6E695C7D7038524 + +YMB2rcNobMEfCRzLcGV5uSF5g1hMIuHlJjZHG0QYNpeFdP2pONtgGLH+NIVWbb7B +2dYHUbofywcJTGPigSIm0RUEHquz/+seauRXs0jvN0cEKgEyWVaQZB9yem+V5sJx +guicvKmbWfiV9u004n9G4ue9IxpWwoZp1KixOrJ7GOmRhJsNL8E9MUpJ8kD1eOIY +n8RBuo/sQMyDKinL7npk5IYE3N1tQuVAxpEn2KVXjDIIrl0SeCO5pfJdXA40Sw8Q +6bEF8GogDuEaibw2XzOfqzJsmQRks1STtCqKVnN7b7HjpY3pPgYqMqc9BVKWL3PF +a8G5BSGjjosu3SPuzIIlADlQm65O8Qi/6eZ9thByfGBtXcanSdYZtoprreEikhgC +MYnID949McXvnJTjB1snWni2FYhrWuH6iK4/7/UevFg74She5qKfwuw/YXe+p2pP +Z0ON4olUgG68/aReRoICqDurDW88zklbq8c18ECI8ppBy3tDB85Sey+ybwTliSd7 +FLBhwk/vLuhBlX6kVba8CkBUHqu8T9zECyLK2f7geDUjsw6EVXYy7whJE9LL1Sq0 +cSUpyMb5I6RXOe90zj59sBJddEsllSn2KTMhrJa2LPj+j6Df4PuwmsKdPz+DWo5r +TTAvc3iN9sZbXGjwbjiJulzapNPsfOYXrSlN9KrlkHxvmJQq0Y83ZZqmGE+Z54Z4 +TMfA/rKULJ60BSaBIwVb/NyQC+6iKUpiLDMdWhVEqKXtes7fpHnrHwHYPtTMRc6S +EG+txT5gtUKKuddBTx01UZA67L40RyC6gwbg3zipOY5XFChLQ8O4hjSaDZuQEgik +ewZhJ4ExH17+f3GaNAgPE8OtafSF86jcqt2lowrXbPi1CV9BHSriD/2G1WQycjma +Z8tFSb40fxvWHTiuDs9AyymN3OKpVX/IBm8gFxeitryxSYZ4ZOtsI7fTH+hH74C9 +ceKwu/3iPednzj1NvTpBdQvuEHRzgN/YfABXdJ71WiYRwVtE+hsdPJkKAdNYRXVs +YWJU5Ry5CAyaKZ//XsqqXM6PeACbRfWt6lqHSxnuaJuuh6dn2btJj4hX4Do81bh/ +qwKUwzIVmJCtyEaO1VsslQk7CnLZ2dErIWGnRVkeLY0wMW4qspIZUx7ikgJZZ0sz +XFMwByTkVOtzz24nX3DdhxXfClqk1wrUI50erG6XbCjbuN/XEWbKZNLKUrfxkNys +1GjCXr1qagz6s8igxAHNmK2I9N8lyZSLrqKZf6m5CjyLMHSqj95jEeXL8pw29FLs +0BQnpfuqqTQfonYDSxdHgMPZfT2y+iX5LyIaozTJuQjsDAKXhFbytrSZ9as/kmtB +ne8L04gDLiHcX3K0anLSZN/0N06LiIa9O3qygfBHdtB3iIlBnE+yuGMZGPo2KXSe +4HnU/9E6Sayh3hHEqYtDnfVtNSQhJEwGr+HgX2+wvfQYJCUX/x+2gSN40/aYQ1jI +h9gynY7NK8WybupP8JsjJ8t0UOaFwfXC2har1kq/uChOGnsBI+E+Lkx9mOPkpQ0M ++NkN+HYuZC6dqUJAUZmHdzGPgh5MPZiIwusaW7frswmKko32y9VDfg== +-----END RSA PRIVATE KEY----- +` + PrivateKeyECDSANISTPrime256V1 = ` -----BEGIN EC PARAMETERS----- BggqhkjOPQMBBw== -----END EC PARAMETERS----- @@ -98,14 +130,14 @@ AwEHoUQDQgAEq0gH7B1q2cWMDvYTmFr+xNmbrJBMK9ERmZkSfRfaDmzxqvE56FrB p3aue/xDiaFp9yniuM8lqbTWHwyopraMlA== -----END EC PRIVATE KEY----- ` - PrivateKeyECCNISTPrime256V1WithoutParams = ` + PrivateKeyECDSANISTPrime256V1WithoutParams = ` -----BEGIN EC PRIVATE KEY----- MHcCAQEEIM1u5X+fmuna0jK5NoBO8CRWJiTzopg9xzqjs34dB3osoAoGCCqGSM49 AwEHoUQDQgAEq0gH7B1q2cWMDvYTmFr+xNmbrJBMK9ERmZkSfRfaDmzxqvE56FrB p3aue/xDiaFp9yniuM8lqbTWHwyopraMlA== -----END EC PRIVATE KEY----- ` - PrivateKeyECCNISTSecP384R1 = ` + PrivateKeyECDSANISTSecP384R1 = ` -----BEGIN EC PARAMETERS----- BgUrgQQAIg== -----END EC PARAMETERS----- @@ -116,7 +148,7 @@ cmgIRz1yhqHy1Psw3/z8FhhBkhm1Y0InJ7xxt0CsOYs2/faAOmNcKt3mwwthLcEy 9XVZrwbog5s76datlz/7iVd4Jo7vS88= -----END EC PRIVATE KEY----- ` - PrivateKeyECCNISTSecP384R1WithoutParams = ` + PrivateKeyECDSANISTSecP384R1WithoutParams = ` -----BEGIN EC PRIVATE KEY----- MIGkAgEBBDB563eEBAdLcLBpgUi3WOszJS6JOHkAcAePAWX/fvguKP56brbIsZnl /IlujyM6RACgBwYFK4EEACKhZANiAAStW0BfZ2KCkmBQv9Cc8GT9hoGDRuJvfbj0 @@ -124,39 +156,18 @@ cmgIRz1yhqHy1Psw3/z8FhhBkhm1Y0InJ7xxt0CsOYs2/faAOmNcKt3mwwthLcEy 9XVZrwbog5s76datlz/7iVd4Jo7vS88= -----END EC PRIVATE KEY----- ` - PrivateKeyEncryptedRSA2048 = ` ------BEGIN RSA PRIVATE KEY----- + + PrivateKeyECDSANISTSecP384R1Encrypted = ` +-----BEGIN EC PRIVATE KEY----- Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,A6E695C7D7038524 +DEK-Info: AES-256-CBC,0B0F937007A25C35FBB3DEC9F09C0343 -YMB2rcNobMEfCRzLcGV5uSF5g1hMIuHlJjZHG0QYNpeFdP2pONtgGLH+NIVWbb7B -2dYHUbofywcJTGPigSIm0RUEHquz/+seauRXs0jvN0cEKgEyWVaQZB9yem+V5sJx -guicvKmbWfiV9u004n9G4ue9IxpWwoZp1KixOrJ7GOmRhJsNL8E9MUpJ8kD1eOIY -n8RBuo/sQMyDKinL7npk5IYE3N1tQuVAxpEn2KVXjDIIrl0SeCO5pfJdXA40Sw8Q -6bEF8GogDuEaibw2XzOfqzJsmQRks1STtCqKVnN7b7HjpY3pPgYqMqc9BVKWL3PF -a8G5BSGjjosu3SPuzIIlADlQm65O8Qi/6eZ9thByfGBtXcanSdYZtoprreEikhgC -MYnID949McXvnJTjB1snWni2FYhrWuH6iK4/7/UevFg74She5qKfwuw/YXe+p2pP -Z0ON4olUgG68/aReRoICqDurDW88zklbq8c18ECI8ppBy3tDB85Sey+ybwTliSd7 -FLBhwk/vLuhBlX6kVba8CkBUHqu8T9zECyLK2f7geDUjsw6EVXYy7whJE9LL1Sq0 -cSUpyMb5I6RXOe90zj59sBJddEsllSn2KTMhrJa2LPj+j6Df4PuwmsKdPz+DWo5r -TTAvc3iN9sZbXGjwbjiJulzapNPsfOYXrSlN9KrlkHxvmJQq0Y83ZZqmGE+Z54Z4 -TMfA/rKULJ60BSaBIwVb/NyQC+6iKUpiLDMdWhVEqKXtes7fpHnrHwHYPtTMRc6S -EG+txT5gtUKKuddBTx01UZA67L40RyC6gwbg3zipOY5XFChLQ8O4hjSaDZuQEgik -ewZhJ4ExH17+f3GaNAgPE8OtafSF86jcqt2lowrXbPi1CV9BHSriD/2G1WQycjma -Z8tFSb40fxvWHTiuDs9AyymN3OKpVX/IBm8gFxeitryxSYZ4ZOtsI7fTH+hH74C9 -ceKwu/3iPednzj1NvTpBdQvuEHRzgN/YfABXdJ71WiYRwVtE+hsdPJkKAdNYRXVs -YWJU5Ry5CAyaKZ//XsqqXM6PeACbRfWt6lqHSxnuaJuuh6dn2btJj4hX4Do81bh/ -qwKUwzIVmJCtyEaO1VsslQk7CnLZ2dErIWGnRVkeLY0wMW4qspIZUx7ikgJZZ0sz -XFMwByTkVOtzz24nX3DdhxXfClqk1wrUI50erG6XbCjbuN/XEWbKZNLKUrfxkNys -1GjCXr1qagz6s8igxAHNmK2I9N8lyZSLrqKZf6m5CjyLMHSqj95jEeXL8pw29FLs -0BQnpfuqqTQfonYDSxdHgMPZfT2y+iX5LyIaozTJuQjsDAKXhFbytrSZ9as/kmtB -ne8L04gDLiHcX3K0anLSZN/0N06LiIa9O3qygfBHdtB3iIlBnE+yuGMZGPo2KXSe -4HnU/9E6Sayh3hHEqYtDnfVtNSQhJEwGr+HgX2+wvfQYJCUX/x+2gSN40/aYQ1jI -h9gynY7NK8WybupP8JsjJ8t0UOaFwfXC2har1kq/uChOGnsBI+E+Lkx9mOPkpQ0M -+NkN+HYuZC6dqUJAUZmHdzGPgh5MPZiIwusaW7frswmKko32y9VDfg== ------END RSA PRIVATE KEY----- +KIRWqbmNfP3xnnDE8f9Ndx/aaNvQBPCucQrVHc6ZYpImPnVmIzH/eOZMyio7HQkZ +tH2ggwwI+zSg3cJWTehJaR9j9qiFtPH+UDEA03co2QyIyERk1wI5ev4hv822tmtl +/TrYpdjqNkfDZUcZscuf1VHkjSrAwn+3K0NV5hUGfdhWryZ7B16iKyCJrSrbde4x +E34vrABCPJZtg/O7SbXQL8cURtVoEdbT+AveW3qoh5g= +-----END EC PRIVATE KEY----- ` - SelfSignedRSACertificate = ` -----BEGIN CERTIFICATE----- MIIEIjCCAwqgAwIBAgIJAKfsBagyQeuuMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD @@ -271,7 +282,7 @@ FA21NyLKatm942vrWMsBGrcS -----END PRIVATE KEY----- ` - SelfSignedECCCertificate = ` + SelfSignedECDSACertificate = ` -----BEGIN CERTIFICATE----- MIICiTCCAi+gAwIBAgIJAKVi77tebfBPMAoGCCqGSM49BAMCMIGFMQswCQYDVQQG EwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRy @@ -289,7 +300,7 @@ BAMCA0gAMEUCIDybXtWSTIeyETgLBGitveWAYh8dmBK/Wt3+Jdj/5GF6AiEA95I8 96/cXDmduClIg4CnYLGbkDPsC+3nENEIr92WqgE= -----END CERTIFICATE----- ` - SelfSignedECCPrivateKey = ` + SelfSignedECDSAPrivateKey = ` -----BEGIN EC PARAMETERS----- BggqhkjOPQMBBw== -----END EC PARAMETERS----- @@ -521,13 +532,13 @@ jI///X8MUJs= -----END CERTIFICATE----- ` - CASignedECCCertificateChain = `` - CASignedECCCertificateChainPrivateKey = `` - CASignedECCRootCA = `` + CASignedECDSACertificateChain = `` + CASignedECDSACertificateChainPrivateKey = `` + CASignedECDSARootCA = `` - CASignedNoSkiAkiECCCertificateChain = `` - CASignedNoSkiAkiECCCertificateChainPrivateKey = `` - CASignedNoSkiAkiECCRootCA = `` + CASignedNoSkiAkiECDSACertificateChain = `` + CASignedNoSkiAkiECDSACertificateChainPrivateKey = `` + CASignedNoSkiAkiECDSARootCA = `` ) func TestDecodePrivateKeyPKCS8RSA2048(t *testing.T) { @@ -572,9 +583,9 @@ func TestDecodePrivateKeyPKCS1RSA2048(t *testing.T) { } } -func TestDecodePrivateKeyECCNISTPrime256V1(t *testing.T) { +func TestDecodePrivateKeyECDSANISTPrime256V1(t *testing.T) { - privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTPrime256V1) + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTPrime256V1) if err != nil { t.Fatalf("Unexpected result: " + err.Error()) @@ -610,9 +621,9 @@ func TestDecodePrivateKeyECCNISTPrime256V1(t *testing.T) { } } -func TestDecodePrivateKeyECCNISTPrime256V1WithoutParams(t *testing.T) { +func TestDecodePrivateKeyECDSANISTPrime256V1WithoutParams(t *testing.T) { - privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTPrime256V1WithoutParams) + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTPrime256V1WithoutParams) if err != nil { t.Fatalf("Unexpected result: " + err.Error()) @@ -631,8 +642,8 @@ func TestDecodePrivateKeyECCNISTPrime256V1WithoutParams(t *testing.T) { } } -func TestDecodePrivateKeyECCNISTSecP384R1(t *testing.T) { - privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTSecP384R1) +func TestDecodePrivateKeyECDSANISTSecP384R1(t *testing.T) { + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1) if err != nil { t.Fatalf("Unexpected result: " + err.Error()) @@ -668,8 +679,8 @@ func TestDecodePrivateKeyECCNISTSecP384R1(t *testing.T) { } } -func TestDecodePrivateKeyECCNISTSecP384R1WithoutParams(t *testing.T) { - privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECCNISTSecP384R1WithoutParams) +func TestDecodePrivateKeyECDSANISTSecP384R1WithoutParams(t *testing.T) { + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1WithoutParams) if err != nil { t.Fatalf("Unexpected result: " + err.Error()) @@ -699,13 +710,22 @@ func TestDecodePrivateKeyBadData(t *testing.T) { func TestDecodePrivateKeyRSAEncrypted(t *testing.T) { - // Expected to fail on decode of encrypted pem private key + // Expected to fail on decode of encrypted pem rsa private key privateKey, _, err := decodeRSAPrivateKey(PrivateKeyEncryptedRSA2048) if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") } } +func TestDecodePrivateKeyECDSAEncrypted(t *testing.T) { + + // Expected to fail on decode of encrypted pem ecdsa private key + privateKey, _, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1Encrypted) + if err == nil && privateKey != nil { + t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") + } +} + func TestVerifyAndEncodeCertificateBadData(t *testing.T) { // should fail bad base64 data _, _, _, _, err := verifyCertKeyPair(BadCertData, BadKeyData, "") @@ -884,12 +904,11 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *test } } - -func TestVerifyAndEncodeCertificateECCCertificateKeyPair(t *testing.T) { +func TestVerifyAndEncodeCertificateECDSACertificateKeyPair(t *testing.T) { // Should fail due to unsupported private/public key algorithm - _, _, _, _, err := verifyCertKeyPair(SelfSignedECCCertificate, SelfSignedECCPrivateKey, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "") if err == nil { - t.Fatalf("Unexpected result, cert/key PKI algorithm for ECC is unsupported.") + t.Fatalf("Unexpected result, cert/key PKI algorithm for ECDSA is unsupported.") } } From 15a8a4198a51bc33bdfa70f007131af087203882 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 22:59:06 -0600 Subject: [PATCH 08/18] Add unit test to verify DSA signed x509 certificates are rejected --- .../deliveryservice/keys_test.go | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index e92b592d63..aaa2a24d71 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -309,6 +309,79 @@ MHcCAQEEIPrjdSmSp6D/M6KBOwwz7u/NzO70nBT0U74QSCBWmwAOoAoGCCqGSM49 AwEHoUQDQgAEg6md9g5rb4XGHGX33oDly9Q5SuljX+jLq5R0GaCjRF9qX2W/k2Ix GGCDuz76OvbJ/yWzbMsiiw09KEhUsmX1Jw== -----END EC PRIVATE KEY----- +` + + SelfSignedDSACertificate = ` +-----BEGIN CERTIFICATE----- +MIIF6TCCBY6gAwIBAgIUHRv+ycqq+/HTUnXc3uMefnW3qrowCwYJYIZIAWUDBAMC +MIGsMQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRl +bnZlcjEVMBMGA1UEChMMQ0ROLWluLWEtQm94MRUwEwYDVQQLEwxDRE4taW4tYS1C +b3gxIjAgBgNVBAMUGSouZHNhdGVzdC5teWNkbi5jaWFiLnRlc3QxJzAlBgkqhkiG +9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVzdDAeFw0xOTAzMzAwNDUxMzha +Fw0xOTA0MjkwNDUxMzhaMIGsMQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3Jh +ZG8xDzANBgNVBAcTBkRlbnZlcjEVMBMGA1UEChMMQ0ROLWluLWEtQm94MRUwEwYD +VQQLEwxDRE4taW4tYS1Cb3gxIjAgBgNVBAMUGSouZHNhdGVzdC5teWNkbi5jaWFi +LnRlc3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVzdDCC +A0YwggI5BgcqhkjOOAQBMIICLAKCAQEAkypAr0SzwNcEKDm2kiAx7joazQBU1thr +8eIUZAiMpSnpUH6svCPUilYjqhQVIR2F5Pekh/NcnuGGHkZyCKGbS9xKZnndZ2V4 +TA3HDyvTBv8jnfSfah7QYD77E5ju9A050KVxTZpYhNfboRv0PWg1x/WCzqWtYWPP +s7DFEBPhKZcMRTmnELwbM94pPIyFEEDJLL50k1sqbK35mOc+APDioly1EyUGXj/8 +qsCnFDv8EKH6UG5bO9Q1fGEPTqgCcQKWFrbdc6UYZKu+gScMEyax4YktirTEeX46 +o3VnGKXUwslEZhj+HdAnhJzKOUs3xdwzqVjZ4xxh6oY3oEuxarcXmwIhAMYi2lmV ++b4aP6cuzi3dHEKzm/Z70yQi5F+w5S/g2IvxAoIBAEUB1+oPc59wsNjx7NhmlxXx +IR5Hya+6KHlOP/lK1/s/kcCzDvf7uAMFepgKL2geA1y36fllGPL9wImFh9uZprtK +WA1n6Xt1bTsrfoEdrYhYyo5zSliGVuiZ6VLA3egb8WAoyGe8js8Qd+NWkJrjoQfn +QymLv2Q9rFYpzc73OVMuNJfYmbkCOwqx4NxXuR41tV4o4WFpp+2h4VtES69FdT/y +GAFgYm62qnqgjTvR6/8Pi0mjjps6RBlK6NucKwbd2E3wI/2lIfImEaRANMhbpUaa +grrqTsDBsxRykKS1UdjyZniV4TOV4Xjdc0RF8w9JbvRyKbA+KAgv9p4qGxexrDcD +ggEFAAKCAQA8/GqhpKc6AX1ssmo1EQcMWQo+od7LbVEXYRwi/L6BU3CPUIHSz4bw +AtzlwDvSLI8Tbp1Qzs2VBkcT4KbOiIRw4xAsuW+hHBJast2cA7grCP2c0aTe81FU +Kz7KMoH4Xu/cYgd9TOCvLUT5fqJzjI8Sk5z/eJ0q/3kO57GDNgLi/WHFY9Abn7yb +6MpkNc53mi6glMRc0D0d/W5MrSIrq/w+7lwM685pQ9TbPR0Xoimm4rur4/w92P9Z +ydMp9uDeijwl+qFiUBzne66IWx5GH88FQtuWL4cDuyfxRPs4E2vC3pk37zi1b6qJ +1pmcYSbUKMbENbqLuW9jfNdisVUQByPQo4GbMIGYMAwGA1UdEwQFMAMBAf8wEQYJ +YIZIAYb4QgEBBAQDAgZAMA4GA1UdDwEB/wQEAwIChDAgBgNVHSUBAf8EFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwMwHQYDVR0OBBYEFJ5U5dSqX0eUO8VuLqSYRtvQbMs/ +MCQGA1UdEQQdMBuCGSouZHNhdGVzdC5teWNkbi5jaWFiLnRlc3QwCwYJYIZIAWUD +BAMCA0gAMEUCIBCA3RYYn4DK/nzKK4cTbtmj6V72Ywoh6YJ3taZ18iYIAiEAxV5u +qL6kmx7XWFAhA3NKMW79Cz6hmhDo0ZFPf1G258Q= +-----END CERTIFICATE----- +` + SelfSignedDSAPrivateKey = ` +-----BEGIN DSA PARAMETERS----- +MIICLAKCAQEAkypAr0SzwNcEKDm2kiAx7joazQBU1thr8eIUZAiMpSnpUH6svCPU +ilYjqhQVIR2F5Pekh/NcnuGGHkZyCKGbS9xKZnndZ2V4TA3HDyvTBv8jnfSfah7Q +YD77E5ju9A050KVxTZpYhNfboRv0PWg1x/WCzqWtYWPPs7DFEBPhKZcMRTmnELwb +M94pPIyFEEDJLL50k1sqbK35mOc+APDioly1EyUGXj/8qsCnFDv8EKH6UG5bO9Q1 +fGEPTqgCcQKWFrbdc6UYZKu+gScMEyax4YktirTEeX46o3VnGKXUwslEZhj+HdAn +hJzKOUs3xdwzqVjZ4xxh6oY3oEuxarcXmwIhAMYi2lmV+b4aP6cuzi3dHEKzm/Z7 +0yQi5F+w5S/g2IvxAoIBAEUB1+oPc59wsNjx7NhmlxXxIR5Hya+6KHlOP/lK1/s/ +kcCzDvf7uAMFepgKL2geA1y36fllGPL9wImFh9uZprtKWA1n6Xt1bTsrfoEdrYhY +yo5zSliGVuiZ6VLA3egb8WAoyGe8js8Qd+NWkJrjoQfnQymLv2Q9rFYpzc73OVMu +NJfYmbkCOwqx4NxXuR41tV4o4WFpp+2h4VtES69FdT/yGAFgYm62qnqgjTvR6/8P +i0mjjps6RBlK6NucKwbd2E3wI/2lIfImEaRANMhbpUaagrrqTsDBsxRykKS1Udjy +ZniV4TOV4Xjdc0RF8w9JbvRyKbA+KAgv9p4qGxexrDc= +-----END DSA PARAMETERS----- +-----BEGIN DSA PRIVATE KEY----- +MIIDVQIBAAKCAQEAkypAr0SzwNcEKDm2kiAx7joazQBU1thr8eIUZAiMpSnpUH6s +vCPUilYjqhQVIR2F5Pekh/NcnuGGHkZyCKGbS9xKZnndZ2V4TA3HDyvTBv8jnfSf +ah7QYD77E5ju9A050KVxTZpYhNfboRv0PWg1x/WCzqWtYWPPs7DFEBPhKZcMRTmn +ELwbM94pPIyFEEDJLL50k1sqbK35mOc+APDioly1EyUGXj/8qsCnFDv8EKH6UG5b +O9Q1fGEPTqgCcQKWFrbdc6UYZKu+gScMEyax4YktirTEeX46o3VnGKXUwslEZhj+ +HdAnhJzKOUs3xdwzqVjZ4xxh6oY3oEuxarcXmwIhAMYi2lmV+b4aP6cuzi3dHEKz +m/Z70yQi5F+w5S/g2IvxAoIBAEUB1+oPc59wsNjx7NhmlxXxIR5Hya+6KHlOP/lK +1/s/kcCzDvf7uAMFepgKL2geA1y36fllGPL9wImFh9uZprtKWA1n6Xt1bTsrfoEd +rYhYyo5zSliGVuiZ6VLA3egb8WAoyGe8js8Qd+NWkJrjoQfnQymLv2Q9rFYpzc73 +OVMuNJfYmbkCOwqx4NxXuR41tV4o4WFpp+2h4VtES69FdT/yGAFgYm62qnqgjTvR +6/8Pi0mjjps6RBlK6NucKwbd2E3wI/2lIfImEaRANMhbpUaagrrqTsDBsxRykKS1 +UdjyZniV4TOV4Xjdc0RF8w9JbvRyKbA+KAgv9p4qGxexrDcCggEAPPxqoaSnOgF9 +bLJqNREHDFkKPqHey21RF2EcIvy+gVNwj1CB0s+G8ALc5cA70iyPE26dUM7NlQZH +E+CmzoiEcOMQLLlvoRwSWrLdnAO4Kwj9nNGk3vNRVCs+yjKB+F7v3GIHfUzgry1E ++X6ic4yPEpOc/3idKv95DuexgzYC4v1hxWPQG5+8m+jKZDXOd5ouoJTEXNA9Hf1u +TK0iK6v8Pu5cDOvOaUPU2z0dF6IppuK7q+P8Pdj/WcnTKfbg3oo8JfqhYlAc53uu +iFseRh/PBULbli+HA7sn8UT7OBNrwt6ZN+84tW+qidaZnGEm1CjGxDW6i7lvY3zX +YrFVEAcj0AIgQGLEWrKD5SwnFfhG5QNOjFO6RN/bNB8SanXrnzDUnkE= +-----END DSA PRIVATE KEY----- ` CASignedRSACertificateChain = ` @@ -734,6 +807,15 @@ func TestVerifyAndEncodeCertificateBadData(t *testing.T) { } } +func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairDSA(t *testing.T) { + // should fail due to x509 + DSA being unsupported + _, _, _, _, err := verifyCertKeyPair(SelfSignedDSACertificate, SelfSignedDSAPrivateKey, "") + + if err == nil { + t.Fatalf("Unexpected result: the DSA PKI algorithm is unsupported") + } +} + func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "") From 6bd4977557cc2c396975d83a30b12a9b2864ca49 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Fri, 29 Mar 2019 23:00:33 -0600 Subject: [PATCH 09/18] Gofmt --- .../traffic_ops_golang/deliveryservice/keys.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 2313bb0907..50a00e56a6 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -520,17 +520,16 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) } // Decode PKCS#1 - RSA Private Key - rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil || rsaPrivateKey == nil { + rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil || rsaPrivateKey == nil { msg := fmt.Sprintf("parse pkcs#1 error: %s", err.Error()) decodeErrors = append(decodeErrors, msg) return nil, "", errors.New(collapseErrors(decodeErrors)) } - return rsaPrivateKey, trimmedPrivateKey, nil + return rsaPrivateKey, trimmedPrivateKey, nil } - // decode the private key // check for proper algorithm. // check for correct number of keys @@ -586,7 +585,7 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err } // First try to parse an EC key the normal way, before attempting PKCS8 - ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes); + ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes) if ecdsaPrivateKey == nil || err != nil { msg := fmt.Sprintf("x509.ParseECPrivateKey() error: %s", err.Error()) decodeErrors = append(decodeErrors, msg) @@ -617,4 +616,4 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err func collapseErrors(errStrings []string) string { return fmt.Sprintf("ecdsa decode errors: [%s]", strings.Join(errStrings, ",")) -} \ No newline at end of file +} From b892971d0c5d072234c18097929eeda070b4c20f Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Sat, 30 Mar 2019 13:17:39 -0600 Subject: [PATCH 10/18] Fix ECDSA unit tests Add ECDSA mismatched cert/key unit test Update error messages to be more meaningful --- .../deliveryservice/keys.go | 86 ++++++++------ .../deliveryservice/keys_test.go | 110 +++++++++++++++--- 2 files changed, 148 insertions(+), 48 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 50a00e56a6..ad5cfc2f4d 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -303,29 +303,10 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin return "", "", false, false, errors.New("could not parse the server certificate: " + err.Error()) } - // validate certificate is a server auth certificate if the extension is present - if cert.Version > 1 { - serverAuthExtKeyUsageFound := false - for _, certExtKeyUsage := range cert.ExtKeyUsage { - if certExtKeyUsage == x509.ExtKeyUsageServerAuth { - serverAuthExtKeyUsageFound = true - break - } - } - - if !serverAuthExtKeyUsageFound { - return "", "", false, false, errors.New("version 3 x509 certificate does not have 'server auth' extended key usage") - } - } - - // ensure that the certificate is signed - if len(cert.Signature) == 0 { - return "", "", false, false, errors.New("certificate does not have valid signature") - } - - // verify that the cert has a public key available - if cert.PublicKey == nil { - return "", "", false, false, errors.New("certificate does not have a public key") + // Common x509 certificate validation + err = commonX509CertificateValidation(cert) + if err != nil { + return "", "", false, false, err } switch cert.PublicKeyAlgorithm { @@ -345,12 +326,12 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin // Extract the RSA public key from the x509 certificate certPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) if !ok || certPublicKey == nil { - return "", "", false, false, errors.New("could not get public RSA key from certificate") + return "", "", false, false, errors.New("could not extract public RSA key from certificate") } // Check RSA private key modulus against the x509 RSA public key modulus if rsaPrivateKey != nil && certPublicKey != nil && !bytes.Equal(rsaPrivateKey.N.Bytes(), certPublicKey.N.Bytes()) { - return "", "", false, false, errors.New("private RSA key modulus does not match certificate RSA modulus") + return "", "", false, false, errors.New("cert/key mismatch error: certificate public modulus does not match private key modulus") } case x509.ECDSA: @@ -370,22 +351,22 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin // Extract the ECDSA public key from the x509 certificate certPublicKey, ok := cert.PublicKey.(*ecdsa.PublicKey) if !ok || certPublicKey == nil { - return "", "", false, false, errors.New("could not get public ECDSA key from certificate") + return "", "", false, false, errors.New("could not get extract public ECDSA key from certificate") } // Compare the ECDSA curve name contained within the x509.PublicKey against the curve name indicated in the private key if strings.Compare(certPublicKey.Params().Name, ecdsaPrivateKey.Params().Name) != 0 { - return "", "", false, false, errors.New("ecdsa curve name does not match") + return "", "", false, false, errors.New("cert/key mismatch error: ecdsa curve name in cert does not match curve name in private key") } // Verify that ECDSA public value X matches in both the cert.PublicKey and the private key. if !bytes.Equal(certPublicKey.X.Bytes(), ecdsaPrivateKey.X.Bytes()) { - return "", "", false, false, errors.New("ecdsa public key X value mismatch") + return "", "", false, false, errors.New("cert/key mismatch error: ecdsa public X value mismatch") } // Verify that ECDSA public value Y matches in both the cert.PublicKey and the private key. if !bytes.Equal(certPublicKey.Y.Bytes(), ecdsaPrivateKey.Y.Bytes()) { - return "", "", false, false, errors.New("ecdsa public key Y value mismatch") + return "", "", false, false, errors.New("cert/key mismatch error: ecdsa public Y value mismatch") } case x509.DSA: @@ -446,6 +427,42 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin return pemCertificate, cleanPemPrivateKey, false, false, nil } +func commonX509CertificateValidation(cert *x509.Certificate) error { + + // validate certificate is a server auth certificate if the extension is present + if cert.Version > 1 { + serverAuthExtKeyUsageFound := false + for _, certExtKeyUsage := range cert.ExtKeyUsage { + if certExtKeyUsage == x509.ExtKeyUsageServerAuth { + serverAuthExtKeyUsageFound = true + break + } + } + + if !serverAuthExtKeyUsageFound { + return errors.New("version 3 x509 certificate does not have 'server auth' extended key usage") + } + } + + // ensure that the certificate uses a supported PKI algorithm and a public key is present. + if cert.PublicKey == nil { + return errors.New("certificate contains no PKI public key") + } + if cert.PublicKeyAlgorithm == x509.UnknownPublicKeyAlgorithm { + return errors.New("certificate uses unsupported PKI authentication algorithm") + } + + // ensure that the certificate is signed with supported algorithm + if len(cert.Signature) == 0 { + return errors.New("certificate does not have valid signature") + } + if cert.SignatureAlgorithm == x509.UnknownSignatureAlgorithm { + return errors.New("certificate is signed with unsupported signature algorithm") + } + + return nil +} + // Common privateKey validation logic. // Reject unsupported encrypted private keys func commonPrivateKeyValidation(block *pem.Block) error { @@ -456,7 +473,7 @@ func commonPrivateKeyValidation(block *pem.Block) error { // Check for encrypted keys or other unsupported key types if strings.Contains(block.Type, "ENCRYPTED") { - return errors.New("encrypted private key not supported") + return errors.New("encrypted private key not supported - block type: " + block.Type) } // Check block headers for encryption. @@ -487,7 +504,7 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Check for proper key count before attempting to decode. blockCount := strings.Count(trimmedPrivateKey, "\n-----END") if blockCount < 1 { - return nil, "", errors.New("no private key PEM blocks found") + return nil, "", errors.New("no RSA private key PEM blocks found") } if blockCount > 1 { return nil, "", errors.New("multiple private key PEM blocks found") @@ -566,8 +583,8 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err break } + // Attempt to decode the first PEM Block block, pemData = pem.Decode(pemData) - if block == nil { return nil, "", errors.New("could not decode pem-encoded block") } @@ -587,7 +604,7 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // First try to parse an EC key the normal way, before attempting PKCS8 ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes) if ecdsaPrivateKey == nil || err != nil { - msg := fmt.Sprintf("x509.ParseECPrivateKey() error: %s", err.Error()) + msg := fmt.Sprintf("parse EC ANSI X9.62 error: %s", err.Error()) decodeErrors = append(decodeErrors, msg) } else { return ecdsaPrivateKey, trimmedPrivateKey, nil @@ -596,10 +613,11 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // Second, try to parse PEM block as a PKCS#8 formatted RSA Private Key. privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - msg := fmt.Sprintf("x509.ParsePKCS8PrivateKey() error: %s", err.Error()) + msg := fmt.Sprintf("parse PKCS#8 error: %s", err.Error()) decodeErrors = append(decodeErrors, msg) return nil, "", errors.New(collapseErrors(decodeErrors)) } + // Make sure the privateKey is of the correct type (ecdsa.PrivateKey) ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) if !ok || ecdsaPrivateKey == nil { diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index aaa2a24d71..7b05e54728 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -156,7 +156,6 @@ cmgIRz1yhqHy1Psw3/z8FhhBkhm1Y0InJ7xxt0CsOYs2/faAOmNcKt3mwwthLcEy 9XVZrwbog5s76datlz/7iVd4Jo7vS88= -----END EC PRIVATE KEY----- ` - PrivateKeyECDSANISTSecP384R1Encrypted = ` -----BEGIN EC PRIVATE KEY----- Proc-Type: 4,ENCRYPTED @@ -225,7 +224,6 @@ oIuOOmvkBAyy0cHT/BSunqxiFOWcu9yb+2MfSWaHHxNj3kteif8Oai1lL84JOucC /FZTue8KxnrjBcbGYYtwPCU= -----END PRIVATE KEY----- ` - SelfSignedNOSKIAKIRSACertificate = ` -----BEGIN CERTIFICATE----- MIID4DCCAsigAwIBAgIJAI84W5tsR3z4MA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD @@ -281,8 +279,7 @@ XkhQHb96BsPSpUioe5MLzr5EnDLLV8Hptf4mmJctkd0eczgvtlX9QyFp9LpeqAMQ FA21NyLKatm942vrWMsBGrcS -----END PRIVATE KEY----- ` - - SelfSignedECDSACertificate = ` + SelfSignedECDSACertificateNoDigitalSignatureKeyUsage = ` -----BEGIN CERTIFICATE----- MIICiTCCAi+gAwIBAgIJAKVi77tebfBPMAoGCCqGSM49BAMCMIGFMQswCQYDVQQG EwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRy @@ -300,7 +297,7 @@ BAMCA0gAMEUCIDybXtWSTIeyETgLBGitveWAYh8dmBK/Wt3+Jdj/5GF6AiEA95I8 96/cXDmduClIg4CnYLGbkDPsC+3nENEIr92WqgE= -----END CERTIFICATE----- ` - SelfSignedECDSAPrivateKey = ` + SelfSignedECDSAPrivateKeyNoDigitalSignatureKeyUsage = ` -----BEGIN EC PARAMETERS----- BggqhkjOPQMBBw== -----END EC PARAMETERS----- @@ -310,7 +307,44 @@ AwEHoUQDQgAEg6md9g5rb4XGHGX33oDly9Q5SuljX+jLq5R0GaCjRF9qX2W/k2Ix GGCDuz76OvbJ/yWzbMsiiw09KEhUsmX1Jw== -----END EC PRIVATE KEY----- ` - + SelfSignedECDSACertificate = ` +-----BEGIN CERTIFICATE----- +MIIC/jCCAqSgAwIBAgIUXHzSgl46W/BuBZ+Vf8qyBa/qVZwwCgYIKoZIzj0EAwIw +ga4xCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVu +dmVyMRUwEwYDVQQKEwxDRE4taW4tYS1Cb3gxFTATBgNVBAsTDENETi1pbi1hLUJv +eDEkMCIGA1UEAxQbKi5lY2RzYXRlc3QubXljZG4uY2lhYi50ZXN0MScwJQYJKoZI +hvcNAQkBFhhuby1yZXBseUBpbmZyYS5jaWFiLnRlc3QwHhcNMTkwMzMwMTgyMTIx +WhcNMTkwNDI5MTgyMTIxWjCBrjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9y +YWRvMQ8wDQYDVQQHEwZEZW52ZXIxFTATBgNVBAoTDENETi1pbi1hLUJveDEVMBMG +A1UECxMMQ0ROLWluLWEtQm94MSQwIgYDVQQDFBsqLmVjZHNhdGVzdC5teWNkbi5j +aWFiLnRlc3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVz +dDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABB1UpeDr4LCoxdYwziBAWpNJGeUK +3ikfqHn9dFr/p9I3j24yo9lJcvjGB7LP0euKr0Qjnsgm1cq6xR2meFEfutGjgZ0w +gZowDAYDVR0TBAUwAwEB/zARBglghkgBhvhCAQEEBAMCBkAwDgYDVR0PAQH/BAQD +AgKEMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAzAdBgNVHQ4EFgQU +ASswQL7PBDEAWVySy/6K3UBrP8owJgYDVR0RBB8wHYIbKi5lY2RzYXRlc3QubXlj +ZG4uY2lhYi50ZXN0MAoGCCqGSM49BAMCA0gAMEUCIFS0uTwkNybSS/m+DbkDAi0j +FueoHu2+4E9uF4iy6g9jAiEA5IQfSN4S4Oyr6fQkFZx7OrymvechwOXjHcxa7BmB +zo8= +-----END CERTIFICATE----- +` + SelfSignedECDSAPrivateKey = ` +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINVb8yaaCT14CVhYVaOv3fmGpEVuXvTclOQYIZq793svoAoGCCqGSM49 +AwEHoUQDQgAEHVSl4OvgsKjF1jDOIEBak0kZ5QreKR+oef10Wv+n0jePbjKj2Uly ++MYHss/R64qvRCOeyCbVyrrFHaZ4UR+60Q== +-----END EC PRIVATE KEY----- +` + SelfSignedECDSAPrivateKeyWithoutParams = ` +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINVb8yaaCT14CVhYVaOv3fmGpEVuXvTclOQYIZq793svoAoGCCqGSM49 +AwEHoUQDQgAEHVSl4OvgsKjF1jDOIEBak0kZ5QreKR+oef10Wv+n0jePbjKj2Uly ++MYHss/R64qvRCOeyCbVyrrFHaZ4UR+60Q== +-----END EC PRIVATE KEY----- +` SelfSignedDSACertificate = ` -----BEGIN CERTIFICATE----- MIIF6TCCBY6gAwIBAgIUHRv+ycqq+/HTUnXc3uMefnW3qrowCwYJYIZIAWUDBAMC @@ -383,7 +417,6 @@ iFseRh/PBULbli+HA7sn8UT7OBNrwt6ZN+84tW+qidaZnGEm1CjGxDW6i7lvY3zX YrFVEAcj0AIgQGLEWrKD5SwnFfhG5QNOjFO6RN/bNB8SanXrnzDUnkE= -----END DSA PRIVATE KEY----- ` - CASignedRSACertificateChain = ` -----BEGIN CERTIFICATE----- MIIE+zCCA+OgAwIBAgIFFVGJEGcwDQYJKoZIhvcNAQELBQAwga0xCzAJBgNVBAYT @@ -497,7 +530,6 @@ GcDuf0HznG/JMOtoGmMELyxJlIHCBPG1h+myLON9/XuPHlhMQcIhmqNEBBGwSdwm 1Ybc3W8sUkBAEha1Nm4SGJOz2Lfk/rAZ -----END CERTIFICATE----- ` - CASignedNoSkiAkiRSACertificateChain = ` -----BEGIN CERTIFICATE----- MIID/zCCAuegAwIBAgIFFVGJhGIwDQYJKoZIhvcNAQELBQAwga0xCzAJBgNVBAYT @@ -772,12 +804,25 @@ func TestDecodePrivateKeyECDSANISTSecP384R1WithoutParams(t *testing.T) { } } -func TestDecodePrivateKeyBadData(t *testing.T) { +func TestDecodeRSAPrivateKeyBadData(t *testing.T) { // Expected to fail. privateKey, _, err := decodeRSAPrivateKey(BadKeyData) if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of bad private key data should have returned an error") + } else { + t.Logf("Expected Error Msg: %s", err.Error()) + } +} + +func TestDecodeECDSAPrivateKeyBadData(t *testing.T) { + + // Expected to fail. + privateKey, _, err := decodeECDSAPrivateKey(BadKeyData) + if err == nil && privateKey != nil { + t.Fatal("unexpected result: decoding of bad private key data should have returned an error") + } else { + t.Logf("Expected Error Msg: %s", err.Error()) } } @@ -787,6 +832,8 @@ func TestDecodePrivateKeyRSAEncrypted(t *testing.T) { privateKey, _, err := decodeRSAPrivateKey(PrivateKeyEncryptedRSA2048) if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") + } else { + t.Logf("Expected Error Msg: %s", err.Error()) } } @@ -796,6 +843,8 @@ func TestDecodePrivateKeyECDSAEncrypted(t *testing.T) { privateKey, _, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1Encrypted) if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") + } else { + t.Logf("Expected Error Msg: %s", err.Error()) } } @@ -875,6 +924,8 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t * if err == nil { t.Fatalf("Unexpected result, a certificate/key modulus mismatch error should have occurred") + } else { + t.Logf("Expected Error Msg: %s", err.Error()) } } @@ -965,11 +1016,11 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *test certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, CASignedNoSkiAkiRSARootCA) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } if unknownAuth { - t.Fatalf("Unexpected result: warning for unknown authority even though rootCA is in certChain") + t.Fatalf("unexpected result: warning for unknown authority even though rootCA is in certChain") } // Decode the clean Private Key @@ -982,15 +1033,46 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *test } if len(certChain) == 0 { - t.Fatal("unexpected: certchain should not empty") + t.Fatal("unexpected: cert chain should not empty") } } -func TestVerifyAndEncodeCertificateECDSACertificateKeyPair(t *testing.T) { +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutDigitalSignatureKeyUsage(t *testing.T) { // Should fail due to unsupported private/public key algorithm - _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificateNoDigitalSignatureKeyUsage, SelfSignedECDSAPrivateKeyNoDigitalSignatureKeyUsage, "") if err == nil { t.Fatalf("Unexpected result, cert/key PKI algorithm for ECDSA is unsupported.") + } else { + t.Logf("Expected Error Msg: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPair(t *testing.T) { + // Should be successfull as the certificate and key are valid with proper keyUsage/extendedKeyUsage. + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "") + + if err != nil { + t.Fatalf("Unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutParams(t *testing.T) { + // Test result should be successful as the certificate and key are valid with proper keyUsage/extendedKeyUsage. + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKeyWithoutParams, "") + + if err != nil { + t.Fatalf("Unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairMisMatchedPrivateKey(t *testing.T) { + // Should fail due to mismatched ECDSA cert/private key pair + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, PrivateKeyECDSANISTPrime256V1, "") + + if err == nil { + t.Fatalf("Unexpected Result: Mismatched ECDSA cert/key pair should have failed verification") + } else { + t.Logf("Expected Error Msg: %s", err.Error()) } } From b4da1d83f4f17b55d37f0d8af5942d86b2b6396e Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Sat, 30 Mar 2019 14:15:10 -0600 Subject: [PATCH 11/18] Add more unit tests related to critical x509 cert/key validation Missing RSA keyEncipherment unit test Missing ECDSA digitalSignature unit test Missing serverAuth extendedKeyUsage (x509v3 only) unit test --- .../deliveryservice/keys.go | 89 ++++---- .../deliveryservice/keys_test.go | 204 +++++++++++++++--- 2 files changed, 218 insertions(+), 75 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index ad5cfc2f4d..3467783387 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -29,6 +29,7 @@ import ( "encoding/pem" "errors" "fmt" + "github.com/apache/trafficcontrol/lib/go-util" "net/http" "strings" @@ -317,7 +318,7 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin // usage must be indicated in the certificate. // The keyUsage and extended Key Usage does not exist in version 1 of the x509 specificication. if cert.Version > 1 && !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) { - return "", "", false, false, errors.New("no key encipherment usage indicated for the RSA server certificate") + return "", "", false, false, errors.New("cert/key (rsa) validation: no keyEncipherment keyUsage extension present in x509v3 server certificate") } // Attempt to decode the RSA private key @@ -326,12 +327,12 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin // Extract the RSA public key from the x509 certificate certPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) if !ok || certPublicKey == nil { - return "", "", false, false, errors.New("could not extract public RSA key from certificate") + return "", "", false, false, errors.New("cert/key (rsa) validation error: could not extract public RSA key from certificate") } // Check RSA private key modulus against the x509 RSA public key modulus if rsaPrivateKey != nil && certPublicKey != nil && !bytes.Equal(rsaPrivateKey.N.Bytes(), certPublicKey.N.Bytes()) { - return "", "", false, false, errors.New("cert/key mismatch error: certificate public modulus does not match private key modulus") + return "", "", false, false, errors.New("cert/key (rsa) mismatch error: RSA public N modulus value mismatch") } case x509.ECDSA: @@ -342,7 +343,7 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin // DSA and ECDSA is not an encryption algorithm and only a signing algorithm, hence the // certificate only needs to have the DigitalSignature KeyUsage indicated. if cert.Version > 1 && !(cert.KeyUsage&x509.KeyUsageDigitalSignature > 0) { - return "", "", false, false, errors.New("no digital signature usage indicated for the ECDSA server certificate") + return "", "", false, false, errors.New("cert/key (ecdsa) validation error: no digitalSignature keyUsage extension present in x509v3 server certificate") } // Attempt to decode the ECDSA private key @@ -351,29 +352,31 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin // Extract the ECDSA public key from the x509 certificate certPublicKey, ok := cert.PublicKey.(*ecdsa.PublicKey) if !ok || certPublicKey == nil { - return "", "", false, false, errors.New("could not get extract public ECDSA key from certificate") + return "", "", false, false, errors.New("cert/key (ecdsa) validation error: could not get extract public ECDSA key from certificate") } // Compare the ECDSA curve name contained within the x509.PublicKey against the curve name indicated in the private key if strings.Compare(certPublicKey.Params().Name, ecdsaPrivateKey.Params().Name) != 0 { - return "", "", false, false, errors.New("cert/key mismatch error: ecdsa curve name in cert does not match curve name in private key") + return "", "", false, false, errors.New("cert/key (ecdsa) mismatch error: ECDSA curve name in cert does not match curve name in private key") } // Verify that ECDSA public value X matches in both the cert.PublicKey and the private key. if !bytes.Equal(certPublicKey.X.Bytes(), ecdsaPrivateKey.X.Bytes()) { - return "", "", false, false, errors.New("cert/key mismatch error: ecdsa public X value mismatch") + return "", "", false, false, errors.New("cert/key (ecdsa) mismatch error: ECDSA public X value mismatch") } // Verify that ECDSA public value Y matches in both the cert.PublicKey and the private key. if !bytes.Equal(certPublicKey.Y.Bytes(), ecdsaPrivateKey.Y.Bytes()) { - return "", "", false, false, errors.New("cert/key mismatch error: ecdsa public Y value mismatch") + return "", "", false, false, errors.New("cert/key (ecdsa) mismatch error: ECDSA public Y value mismatch") } case x509.DSA: - return "", "", false, false, errors.New("certificate is signed with unsupported DSA PKI algorithm") + return "", "", false, false, errors.New("cert/key validation error: DSA public key algorithm unsupported") + case x509.UnknownPublicKeyAlgorithm: + fallthrough default: - return "", "", false, false, errors.New("certificate is signed with an unsupported PKI authentication algorithm") + return "", "", false, false, errors.New("cert/key validation error: Unknown public key algorithm") } bundle := "" @@ -440,24 +443,24 @@ func commonX509CertificateValidation(cert *x509.Certificate) error { } if !serverAuthExtKeyUsageFound { - return errors.New("version 3 x509 certificate does not have 'server auth' extended key usage") + return errors.New("certificate (x509v3) validation error: server certificate missing 'serverAuth' extended key usage") } } // ensure that the certificate uses a supported PKI algorithm and a public key is present. if cert.PublicKey == nil { - return errors.New("certificate contains no PKI public key") + return errors.New("certificate validation error: no PKI public key found") } if cert.PublicKeyAlgorithm == x509.UnknownPublicKeyAlgorithm { - return errors.New("certificate uses unsupported PKI authentication algorithm") + return errors.New("certificate validation error: unknown PKI algorithm") } // ensure that the certificate is signed with supported algorithm if len(cert.Signature) == 0 { - return errors.New("certificate does not have valid signature") + return errors.New("certificate validation error: no signature found") } if cert.SignatureAlgorithm == x509.UnknownSignatureAlgorithm { - return errors.New("certificate is signed with unsupported signature algorithm") + return errors.New("certificate validation error: unknown signature algorithm") } return nil @@ -468,18 +471,18 @@ func commonX509CertificateValidation(cert *x509.Certificate) error { func commonPrivateKeyValidation(block *pem.Block) error { if block == nil { - return errors.New("could not decode pem-encoded private key") + return errors.New("private key validation error: could not decode pem-encoded private key") } // Check for encrypted keys or other unsupported key types if strings.Contains(block.Type, "ENCRYPTED") { - return errors.New("encrypted private key not supported - block type: " + block.Type) + return errors.New("private key validation error: encrypted private key not supported - block type: " + block.Type) } // Check block headers for encryption. for _, value := range block.Headers { if strings.Contains(value, "ENCRYPTED") { - return errors.New("encrypted private key not supported - header: " + value) + return errors.New("private key validation error: encrypted private key not supported - header: " + value) } } @@ -496,7 +499,7 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) // Capture all key decode errors and collapse them at the end - var decodeErrors = make([]string, 0) + var decodeErrors = make([]error, 0) // RSA Private Key var rsaPrivateKey *rsa.PrivateKey = nil @@ -504,10 +507,10 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Check for proper key count before attempting to decode. blockCount := strings.Count(trimmedPrivateKey, "\n-----END") if blockCount < 1 { - return nil, "", errors.New("no RSA private key PEM blocks found") + return nil, "", errors.New("private key validation error: no RSA private key PEM blocks found") } if blockCount > 1 { - return nil, "", errors.New("multiple private key PEM blocks found") + return nil, "", errors.New("private key validation error: multiple private key PEM blocks found") } // Attempt to decode pem encoded text into PEM block. @@ -523,15 +526,15 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Decode PKCS#8 - RSA Private Key privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - msg := fmt.Sprintf("parse pkcs#8 error: %s", err.Error()) - decodeErrors = append(decodeErrors, msg) + msg := fmt.Sprintf("private key validation error: parse pkcs#8 error - %s", err.Error()) + decodeErrors = append(decodeErrors, errors.New(msg)) } // Determine if the privateKey is of the correct type rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey) if !ok || rsaPrivateKey == nil { - msg := fmt.Sprintf("private key algorithm not supported: %T", privateKey) - decodeErrors = append(decodeErrors, msg) + msg := fmt.Sprintf("private key validation error: incorrect private key type - %T", privateKey) + decodeErrors = append(decodeErrors, errors.New(msg)) } else { return rsaPrivateKey, trimmedPrivateKey, nil } @@ -539,9 +542,9 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Decode PKCS#1 - RSA Private Key rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil || rsaPrivateKey == nil { - msg := fmt.Sprintf("parse pkcs#1 error: %s", err.Error()) - decodeErrors = append(decodeErrors, msg) - return nil, "", errors.New(collapseErrors(decodeErrors)) + msg := fmt.Sprintf("private key validation error: parse pkcs#1 error: %s", err.Error()) + decodeErrors = append(decodeErrors, errors.New(msg)) + return nil, "", util.JoinErrsSep(decodeErrors, ", ") } return rsaPrivateKey, trimmedPrivateKey, nil @@ -559,18 +562,18 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) // Capture all key decode errors and collapse them at the end - var decodeErrors = make([]string, 0) + var decodeErrors = make([]error, 0) // Check for proper key count before attempting to decode. // ECDSA keys can have 1 or 2 PEM blocks if the 'EC PARAM' block is included. var blockCount = strings.Count(trimmedPrivateKey, "\n-----END") if blockCount < 1 { - return nil, "", errors.New("no EC private key PEM blocks found") + return nil, "", errors.New("private key validation error: no EC private key PEM blocks found") } if blockCount > 2 { - return nil, "", errors.New("too many EC related PEM blocks found") + return nil, "", errors.New("private key validation error: too many EC related PEM blocks found") } // Attempt to decode pem encoded text into PEM block. @@ -586,7 +589,7 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // Attempt to decode the first PEM Block block, pemData = pem.Decode(pemData) if block == nil { - return nil, "", errors.New("could not decode pem-encoded block") + return nil, "", errors.New("private key validation error: could not decode pem-encoded block") } // Check that the key was decoded and validate key isn't encrypted and @@ -604,8 +607,8 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // First try to parse an EC key the normal way, before attempting PKCS8 ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes) if ecdsaPrivateKey == nil || err != nil { - msg := fmt.Sprintf("parse EC ANSI X9.62 error: %s", err.Error()) - decodeErrors = append(decodeErrors, msg) + msg := fmt.Sprintf("private key validation error: failed to parse EC ANSI X9.62 - %s", err.Error()) + decodeErrors = append(decodeErrors, errors.New(msg)) } else { return ecdsaPrivateKey, trimmedPrivateKey, nil } @@ -613,25 +616,21 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // Second, try to parse PEM block as a PKCS#8 formatted RSA Private Key. privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - msg := fmt.Sprintf("parse PKCS#8 error: %s", err.Error()) - decodeErrors = append(decodeErrors, msg) - return nil, "", errors.New(collapseErrors(decodeErrors)) + msg := fmt.Sprintf("private key validation error: parse pkcs#8 error - %s", err.Error()) + decodeErrors = append(decodeErrors, errors.New(msg)) + return nil, "", util.JoinErrsSep(decodeErrors, ", ") } // Make sure the privateKey is of the correct type (ecdsa.PrivateKey) ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) if !ok || ecdsaPrivateKey == nil { - msg := fmt.Sprintf("private key algorithm not supported: %T", privateKey) - decodeErrors = append(decodeErrors, msg) - return nil, "", errors.New(collapseErrors(decodeErrors)) + msg := fmt.Sprintf("private key validation error: incorrect private key type - %T", privateKey) + decodeErrors = append(decodeErrors, errors.New(msg)) + return nil, "", util.JoinErrsSep(decodeErrors, ", ") } return ecdsaPrivateKey, trimmedPrivateKey, nil } - return nil, "", errors.New("no ECDSA private keys found") -} - -func collapseErrors(errStrings []string) string { - return fmt.Sprintf("ecdsa decode errors: [%s]", strings.Join(errStrings, ",")) + return nil, "", errors.New("private key validation error: no ECDSA private keys found") } diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index 7b05e54728..253f8e249c 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -223,6 +223,122 @@ m91MxJsaFi3FZ2Pv60ghqG27X8uPbgvGXkTmmcqgAaR/Fh8b1UH+yqOnPUiremxO oIuOOmvkBAyy0cHT/BSunqxiFOWcu9yb+2MfSWaHHxNj3kteif8Oai1lL84JOucC /FZTue8KxnrjBcbGYYtwPCU= -----END PRIVATE KEY----- +` + SelfSignedRSACertificateNoServerAuthExtKeyUsage = ` +-----BEGIN CERTIFICATE----- +MIIEiTCCA3GgAwIBAgIUK/LEzHDA/Hf2aGdnDSka1jov0uswDQYJKoZIhvcNAQEL +BQAwgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMG +RGVudmVyMRUwEwYDVQQKEwxDRE4taW4tYS1Cb3gxFTATBgNVBAsTDENETi1pbi1h +LUJveDEnMCUGA1UEAxQeKi5ub3NlcnZlcmF1dGgubXljZG4uY2lhYi50ZXN0MScw +JQYJKoZIhvcNAQkBFhhuby1yZXBseUBpbmZyYS5jaWFiLnRlc3QwHhcNMTkwMzMw +MTkyNDMwWhcNMTkwNDI5MTkyNDMwWjCBsTELMAkGA1UEBhMCVVMxETAPBgNVBAgT +CENvbG9yYWRvMQ8wDQYDVQQHEwZEZW52ZXIxFTATBgNVBAoTDENETi1pbi1hLUJv +eDEVMBMGA1UECxMMQ0ROLWluLWEtQm94MScwJQYDVQQDFB4qLm5vc2VydmVyYXV0 +aC5teWNkbi5jaWFiLnRlc3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJh +LmNpYWIudGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKfcO00F +XWEnW9cWYSvw/SzmFB02q8ILFyfbFmkxbDDIZyCmiZIoc5xQdgOU9ZcwwS4Xc6Ae +mVbvLn+L/nw50/w7+cX7BSAwMbcANKrgr0OSqHrmvXSZ7xpn7DWb3nrbphnIzRMf +CiQs76cygXV23u8NO4Qed/mlapUYux+SA4t8wVr3ZN8gcoal4f4kv2dZ/nZAXjPY +EAugZxP+hsKF6IhlADOFDssOBUWXB+TE54z9wdUVwovOSOQoPOpoVsc8rcVGHkGm +pjXnd5CcgLv9M1k7gS7nEElUwNWGAY4e0RJqDy32ft9PlGaTVLNxAKzSC49GQBWu +hJGZ7AmgyRIqfB8CAwEAAaOBljCBkzAMBgNVHRMEBTADAQH/MBEGCWCGSAGG+EIB +AQQEAwIGQDAOBgNVHQ8BAf8EBAMCAiQwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwMw +HQYDVR0OBBYEFGGKXpBZaG8HuUnjoI6cqZenJdwVMCkGA1UdEQQiMCCCHioubm9z +ZXJ2ZXJhdXRoLm15Y2RuLmNpYWIudGVzdDANBgkqhkiG9w0BAQsFAAOCAQEAU99E +B0FUyyB90tlGQuMcl3FPRGXwfzSZgqTzdVDAtYNoYO0iqUgzjPhdZyV8Ai8zXbzI +qBiJfqbfu9hsR3l7snjxgXgEXhfYpZO1xyA0TJNrWWmcw/HRTndBclzhBgo8qunF +euO8CSUuZ1QY+cjptM8AQFlgj3PYNOEN2horwCl08Z3K858kOaH8CQ1mHBEonlaj +mGCqKyoQftLi8bmA/PZMOQoIGdgsIsGtt0p4cOJ2+fEwJ1Y0uGT84cOtq8zcHaRl +xqG7Q0ClQAeUC8PuCOZ37tRDdSJ+P/7RGJsiXCA3U8mRJg7nv4pCMEwJUkbhMoXz +RW/yw0YwdzYB21veHQ== +-----END CERTIFICATE----- +` + SelfSignedRSAPrivateKeyNoServerAuthExtKeyUsage = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAp9w7TQVdYSdb1xZhK/D9LOYUHTarwgsXJ9sWaTFsMMhnIKaJ +kihznFB2A5T1lzDBLhdzoB6ZVu8uf4v+fDnT/Dv5xfsFIDAxtwA0quCvQ5Koeua9 +dJnvGmfsNZveetumGcjNEx8KJCzvpzKBdXbe7w07hB53+aVqlRi7H5IDi3zBWvdk +3yByhqXh/iS/Z1n+dkBeM9gQC6BnE/6GwoXoiGUAM4UOyw4FRZcH5MTnjP3B1RXC +i85I5Cg86mhWxzytxUYeQaamNed3kJyAu/0zWTuBLucQSVTA1YYBjh7REmoPLfZ+ +30+UZpNUs3EArNILj0ZAFa6EkZnsCaDJEip8HwIDAQABAoIBAGWau9ZaGfS1szSV +GkpTu5uSxLgOIJb6yZBZX85amQdKNoof5AOxMpF6boSqhKF4ZGY20cko3F4vtrCD +l42wHy19TCnXUHn0UhNYL4kDKXM4cXy68BCFIKKWJvcoGtm43GidD+y0DBprjMBi +pNPqGPUPyGenXa2hv8rxxkpMwpKJ/JHdONq0m+eTu3lCRdxhVVHbOn1xQmJTgP2B +CyrtmBD7rJ5AhDNYQ7GfL9WwVf1UeFNaOuAOEK9T7Weqm3Ak5Pd1dJUwukXk/vND +Rcu+cWhklNTVIUw9XwXawPpFm03iZiTcFurAcrShXrtW7aY38S1e7w1fRSSxhrfQ +GroShXECgYEA3rjHANz5dx/Z0EUQ3rK6MgOuKpsS4rAmpydqY7PFfNkSgQzsUwot +o4VRIiKd16voodvT9CZausgCut6ZqCpVgwZY0Mg9FBEBXfxPIOg5oRNmje7RHAfD +Q9I2yiEgBZ6exi3m4lZKgWSNvKkocY/HLIwsDz4kEq4ux3Gr2+zkIacCgYEAwPD5 +N0R25aO06gI/eeYOV0P0Y0h3OKCtF0b/PwU4tKSuqQiojeIvmoJspbCZJbg+D6Da +0kXgEhybchVBSzgeOggZb+sZl0Odg1eqJea/kbz7JyO0NcZu3t7wg5AVynssF6s0 +JUcDFxELfW9GYLtdzR8LeWvgaezSwZBeYmV1cMkCgYBtri1CPZAUm/jV2c1O/lE3 +ZByXGrsYK4s9cemwo80ziGrWZpjS5AZJqtOjrcxxc1UisHEWoPS5WtoNUKX27LIj +zjJazuFVSnKT6DbHi9Ulf7pXVy5fUWtVsOYOcHWmjtC948j52Wjjg7NRHzStiBKb +24OvFfkJwgGDcnUh3u0RrQKBgG7ZxAVp03nKXYXY9sk9UN34T+++0ah6QBhQlROL +F3JJ74N0Uwr5eeompu9nEAYo3ZczDqWiucMOJo0cAyCJRGyI/LxdcZ2Dnnq4oiwW +b9f2oMFy9PW0ZTytD7g2zx4/OCz9Ev+b1f2psFVH2kJ3Q8Q24uvG++8/vjKxlFip +/BhpAoGAJmo5n5fR9+q1Zwb4Gs9i/gquxcJsWo9eaCgQpt+IK0oqqgi/8xx61PCW +Xeg+Gf0gAv5J/WfbYpBCLD4K8o1COm7ZqZGqG3kFTWYjh0jRm8hLQF+8kkn0Fby5 +ohq7Fw9P96opYCnxqau5nfiHExfyfLNQZlj7dPHZZPCEhUFYSSo= +-----END RSA PRIVATE KEY----- +` + SelfSignedRSACertificateNoKeyEnciphermentKeyUsage = ` +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIUXy/RKN+PEOQwwlsQYJ4FR7HUZn0wDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMG +RGVudmVyMRUwEwYDVQQKEwxDRE4taW4tYS1Cb3gxFTATBgNVBAsTDENETi1pbi1h +LUJveDEsMCoGA1UEAxQjKi5ub2tleWVuY2lwaGVybWVudC5teWNkbi5jaWFiLnRl +c3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVzdDAeFw0x +OTAzMzAxOTI5MTZaFw0xOTA0MjkxOTI5MTZaMIG2MQswCQYDVQQGEwJVUzERMA8G +A1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZlcjEVMBMGA1UEChMMQ0ROLWlu +LWEtQm94MRUwEwYDVQQLEwxDRE4taW4tYS1Cb3gxLDAqBgNVBAMUIyoubm9rZXll +bmNpcGhlcm1lbnQubXljZG4uY2lhYi50ZXN0MScwJQYJKoZIhvcNAQkBFhhuby1y +ZXBseUBpbmZyYS5jaWFiLnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCiOfGhT8EgpDoMLq088R5HR0MXfgwc9XoFZmB5oyZvTDcQkGJH48Z2tFFt +d3qoa5sbyiu5/I8j/J4+NXvYBLLaTNMTz4fFknFmlssyR3CXUjvh3wlzWVJ0SkA+ +GLfnZdX1zJ+35Grf/bILeV0kl/WKoFEyI9CZW7VbTaRluoCxrINlGtLzi+K+kHRc +lxv4EZ6TcgJZ0lT47OSxUTTTDKH4L2rF6dOltmGiGdsMyhZsIswKbM+eEliEYA6Q +3CT5s/3FwihS27gWJq+ORAKuz77Rl+n3epzWaAfD0M/P+eCPNFEqJgMVw72x7SlD +9eyiNns0iq2OvevjMdiBvy+34jNbAgMBAAGjgaUwgaIwDAYDVR0TBAUwAwEB/zAR +BglghkgBhvhCAQEEBAMCBkAwDgYDVR0PAQH/BAQDAgIEMCAGA1UdJQEB/wQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAzAdBgNVHQ4EFgQUtUhWjz+wVZTK5DXkyiqEGVp4 +tvgwLgYDVR0RBCcwJYIjKi5ub2tleWVuY2lwaGVybWVudC5teWNkbi5jaWFiLnRl +c3QwDQYJKoZIhvcNAQELBQADggEBAFClaIKSL0wdeXP94UAcsruRaQyQiOxcx8uu +k3MvMyUXyyTZIMUkKdIetc9uDfcEELJ0QfAKQPNzSEDHniq7b/Tlp5BnmfhMcWFQ +zmegfM/J3xAsJE02IHEKOuyUw9Vm96mzVQ2QfoHcJaBRpl62oHr0PD6R168aSqTe +eqnBe9O03+2WA99Fr6SZDVsOoZFoWYiMBqphKtLDEBvc40v0Tk9oSjOnRNnvPEW2 +JLO38D82IakS2TNQh49tYGwZmLqbXzqLCJ4hqMHsk5lgOzXwc20wM5864fpb+fp0 +eO1J8sGqqiTmh8bnyo6O3Ru4qIs16LXpW8KLgAohSQej0p6tzlo= +-----END CERTIFICATE----- +` + SelfSignedRSAPrivateKeyNoKeyEnciphermentKeyUsage = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAojnxoU/BIKQ6DC6tPPEeR0dDF34MHPV6BWZgeaMmb0w3EJBi +R+PGdrRRbXd6qGubG8orufyPI/yePjV72ASy2kzTE8+HxZJxZpbLMkdwl1I74d8J +c1lSdEpAPhi352XV9cyft+Rq3/2yC3ldJJf1iqBRMiPQmVu1W02kZbqAsayDZRrS +84vivpB0XJcb+BGek3ICWdJU+OzksVE00wyh+C9qxenTpbZhohnbDMoWbCLMCmzP +nhJYhGAOkNwk+bP9xcIoUtu4FiavjkQCrs++0Zfp93qc1mgHw9DPz/ngjzRRKiYD +FcO9se0pQ/XsojZ7NIqtjr3r4zHYgb8vt+IzWwIDAQABAoIBAEm+Kz+XwIO1A4oM +IcXFGW1vUGk6bAkx8TDJM+u3JT6Ml69Y4sQpH0tQdn9bQ4+RsqV0RmI6E1tZdxly +OISexiqDp6Omv+IoypHG1EFbxiuTPxNSzrn3jYq9Qey4UcjHOvaL+MKf+5EsgqXC +mnuK9Bv6+k3fh/BehtclOSjhGaUpvBj4FFpVm5aQT1PlrfsSJsY8AhAsqyO3mO0Z +ndfSd2u3/T795h7XVyarJlZquaExlAe+rsrmdCciU+0l27Wh9HzY145sDtuzSPGm +A8hWredHQ6qVwz4EpVZUj3HDowHi3krqlQitc144CBA/PejTV7jby0piKAZ8agKK +pCiRvxECgYEAzvBKma1oJWVa3oM1sYsan8RcquqHRQoE2q0xDmKgQPa4mihyXfCV +iPDPc2jw+0/M6fNgFlhVppMVqJyvScIELKH0HsRtoZyDiaoVkmQY/EG4xkS9N3zK +6OXs9y/1nHHFwsKe3EDHuPKWJAHDAx+x9OrQ5o67Vc9MDwmwt4bJiDkCgYEAyK/u +3UNWrBVQuT4k8klI485HCJCV6AO2egONw/dGFeZJ9W20Uw/eWAAuphT6HKqwSlBt +0EwTpjL9dnuoTrS2TcTLq7UwTN9Gw/1VhE1of+nbsa0kWAqDqhpCFMZQ2/X9ehDv +cqFemW4HE1la3E9izwlKGU3ehpHwWjRhJbH8kDMCgYB+uS2l4EgHpoK4AneuCrY6 +ImBxFf/SKmmAlFCXM5RZU/0GAkDPABZCbt1LGneAHoUouy4bYOrKgAXiZFj/fP1b +a6337WgJcLQoaGyfYgbe60xAtjV9NkF3z92GHet1a0KkmtP3ov/rZTrGQAHw9sbe +abGVjtBvous7xj5elP7zGQKBgQC2TtRwHi8LLmXhkemgTCCyCX6P8kCrv0uyNa5A +Gk6JsGT5VopcdmrmiGvYJfA7wHdbWwsXETU8Ys/MJXN05EdECIV426UgACjZ/DYG +dQd8Q+Z21rHQZOTMzwO+uZVU7Hcyv1W2TY+RU9mLoz2eK2O4bljo+csvdj3gw/qI +ctLb7wKBgFOwu2jZJE66DJ2AUz5XgeY0EOSH8ZIpdEtRQriE8R397KHb8Pmt75fJ +F+nJV58mV+vR/r3qlMViq8Cfb8cZz47Dn00Q2udMoOLKLiKgu1yP2pdCs24VbwLF +7FDXBcacw5kMQfw5DxWDqgXqbwl4cdS62m8kRA/idZNqdHtCmICA +-----END RSA PRIVATE KEY----- ` SelfSignedNOSKIAKIRSACertificate = ` -----BEGIN CERTIFICATE----- @@ -651,7 +767,7 @@ func TestDecodePrivateKeyPKCS8RSA2048(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS8RSA2048) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) @@ -672,7 +788,7 @@ func TestDecodePrivateKeyPKCS1RSA2048(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS1RSA2048) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) @@ -693,7 +809,7 @@ func TestDecodePrivateKeyECDSANISTPrime256V1(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTPrime256V1) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } var pemData = []byte(cleanPemPrivateKey) @@ -731,7 +847,7 @@ func TestDecodePrivateKeyECDSANISTPrime256V1WithoutParams(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTPrime256V1WithoutParams) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) @@ -751,7 +867,7 @@ func TestDecodePrivateKeyECDSANISTSecP384R1(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } var pemData = []byte(cleanPemPrivateKey) @@ -788,7 +904,7 @@ func TestDecodePrivateKeyECDSANISTSecP384R1WithoutParams(t *testing.T) { privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1WithoutParams) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) @@ -811,7 +927,7 @@ func TestDecodeRSAPrivateKeyBadData(t *testing.T) { if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of bad private key data should have returned an error") } else { - t.Logf("Expected Error Msg: %s", err.Error()) + t.Logf("expected error message: %s", err.Error()) } } @@ -822,7 +938,7 @@ func TestDecodeECDSAPrivateKeyBadData(t *testing.T) { if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of bad private key data should have returned an error") } else { - t.Logf("Expected Error Msg: %s", err.Error()) + t.Logf("expected error message: %s", err.Error()) } } @@ -833,7 +949,7 @@ func TestDecodePrivateKeyRSAEncrypted(t *testing.T) { if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") } else { - t.Logf("Expected Error Msg: %s", err.Error()) + t.Logf("expected error message: %s", err.Error()) } } @@ -844,7 +960,7 @@ func TestDecodePrivateKeyECDSAEncrypted(t *testing.T) { if err == nil && privateKey != nil { t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") } else { - t.Logf("Expected Error Msg: %s", err.Error()) + t.Logf("expected error message: %s", err.Error()) } } @@ -852,7 +968,7 @@ func TestVerifyAndEncodeCertificateBadData(t *testing.T) { // should fail bad base64 data _, _, _, _, err := verifyCertKeyPair(BadCertData, BadKeyData, "") if err == nil { - t.Fatalf("Unexpected result: there should have been a base64 decoding failure") + t.Fatalf("unexpected result: there should have been a base64 decoding failure") } } @@ -861,7 +977,9 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairDSA(t *testing.T) { _, _, _, _, err := verifyCertKeyPair(SelfSignedDSACertificate, SelfSignedDSAPrivateKey, "") if err == nil { - t.Fatalf("Unexpected result: the DSA PKI algorithm is unsupported") + t.Fatalf("unexpected result: the DSA PKI algorithm is unsupported") + } else { + t.Logf("expected error message: %s", err.Error()) } } @@ -870,11 +988,11 @@ func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "") if err != nil { - t.Fatalf("Unexpected result: a certificate verification error should have occured") + t.Fatalf("unexpected result: a certificate verification error should have occured") } if !unknownAuth { - t.Fatalf("Unexpected result: certificate verification should have detected unknown authority") + t.Fatalf("unexpected result: certificate verification should have detected unknown authority") } // Decode the clean Private Key @@ -896,11 +1014,11 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedRSACertificate, SelfSignedRSAPrivateKey, "") if err != nil { - t.Fatalf("Unexpected result, a certificate verification error should have occured") + t.Fatalf("unexpected result, a certificate verification error should have occured") } if !unknownAuth { - t.Fatalf("Unexpected result, certificate verification should have detected unknown authority") + t.Fatalf("unexpected result, certificate verification should have detected unknown authority") } // Decode the clean Private Key @@ -923,9 +1041,34 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t * _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificate, PrivateKeyPKCS1RSA2048, "") if err == nil { - t.Fatalf("Unexpected result, a certificate/key modulus mismatch error should have occurred") + t.Fatalf("unexpected result: a certificate/key modulus mismatch error should have occurred") } else { - t.Logf("Expected Error Msg: %s", err.Error()) + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateSelfSignedNoServerAuthExtKeyUsage(t *testing.T) { + + // Should fail due to not having the serverAuth extKeyUsage (x509v3 only) + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoServerAuthExtKeyUsage, SelfSignedRSAPrivateKeyNoServerAuthExtKeyUsage, "") + + if err == nil { + t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the server auth extKeyUsage") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateSelfSignedRSANoKeyEnciphermentKeyUsage(t *testing.T) { + + // Should fail due to not having the keyEncipherment keyUsage (x509v3 only) + // keyUsage extension must include keyEncipherment if the PKI algorithm is RSA. + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoKeyEnciphermentKeyUsage, SelfSignedRSAPrivateKeyNoKeyEnciphermentKeyUsage, "") + + if err == nil { + t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the keyEncipherment keyUsage (required for x509v3+RSA certificates)") + } else { + t.Logf("expected error message: %s", err.Error()) } } @@ -935,11 +1078,11 @@ func TestVerifyAndEncodeCertificateCASignedCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, "") if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } if !unknownAuth { - t.Fatalf("Unexpected result, certificate verification should have detected unknown authority") + t.Fatalf("unexpected result, certificate verification should have detected unknown authority") } // Decode the clean Private Key @@ -962,11 +1105,11 @@ func TestVerifyAndEncodeCertificateCASignedCertKeyPairWithRootCA(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, CASignedRSARootCA) if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } if unknownAuth { - t.Fatalf("Unexpected result: warning for unknown authority even though rootCA is in certChain") + t.Fatalf("unexpected result: warning for unknown authority even though rootCA is in certChain") } // Decode the clean Private Key @@ -989,11 +1132,11 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, "") if err != nil { - t.Fatalf("Unexpected result: " + err.Error()) + t.Fatalf("unexpected result: " + err.Error()) } if !unknownAuth { - t.Fatalf("Unexpected result, certificate verification should have detected unknown authority") + t.Fatalf("unexpected result, certificate verification should have detected unknown authority") } // Decode the clean Private Key @@ -1039,12 +1182,13 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *test func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutDigitalSignatureKeyUsage(t *testing.T) { // Should fail due to unsupported private/public key algorithm + // keyUsage must contain the digitalSignature usage if a DSA based PKI algorithm is indicated (unlike RSA). _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificateNoDigitalSignatureKeyUsage, SelfSignedECDSAPrivateKeyNoDigitalSignatureKeyUsage, "") if err == nil { - t.Fatalf("Unexpected result, cert/key PKI algorithm for ECDSA is unsupported.") + t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the digitalSignature keyUsage (required for x509v3+ECDSA certificates)") } else { - t.Logf("Expected Error Msg: %s", err.Error()) + t.Logf("expected error message: %s", err.Error()) } } @@ -1053,7 +1197,7 @@ func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPair(t *testing. _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "") if err != nil { - t.Fatalf("Unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) + t.Fatalf("unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) } } @@ -1062,7 +1206,7 @@ func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutParam _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKeyWithoutParams, "") if err != nil { - t.Fatalf("Unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) + t.Fatalf("unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) } } @@ -1071,8 +1215,8 @@ func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairMisMatchedPr _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, PrivateKeyECDSANISTPrime256V1, "") if err == nil { - t.Fatalf("Unexpected Result: Mismatched ECDSA cert/key pair should have failed verification") + t.Fatalf("unexpected Result: Mismatched ECDSA cert/key pair should have failed verification") } else { - t.Logf("Expected Error Msg: %s", err.Error()) + t.Logf("expected error message: %s", err.Error()) } } From 9ce939e25e7c999e353a9e2134089e898291abd7 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Sat, 30 Mar 2019 22:04:33 -0600 Subject: [PATCH 12/18] Add self-signed x509v1 server certificate unit test. --- .../deliveryservice/keys_test.go | 92 +++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index 253f8e249c..bc35d7a78a 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -532,6 +532,62 @@ TK0iK6v8Pu5cDOvOaUPU2z0dF6IppuK7q+P8Pdj/WcnTKfbg3oo8JfqhYlAc53uu iFseRh/PBULbli+HA7sn8UT7OBNrwt6ZN+84tW+qidaZnGEm1CjGxDW6i7lvY3zX YrFVEAcj0AIgQGLEWrKD5SwnFfhG5QNOjFO6RN/bNB8SanXrnzDUnkE= -----END DSA PRIVATE KEY----- +` + SelfSignedX509v1Certificate = ` +-----BEGIN CERTIFICATE----- +MIID6TCCAtECFCs7N+H5AQ4SN7lVyK+bHTrKgwOGMA0GCSqGSIb3DQEBCwUAMIGw +MQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZl +cjEVMBMGA1UEChMMQ0ROLWluLWEtQm94MRUwEwYDVQQLEwxDRE4taW4tYS1Cb3gx +JjAkBgNVBAMUHSoueDUwOXYxLXRlc3QubXljZG4uY2lhYi50ZXN0MScwJQYJKoZI +hvcNAQkBFhhuby1yZXBseUBpbmZyYS5jaWFiLnRlc3QwHhcNMTkwMzMxMDM1MDU4 +WhcNMTkwNDMwMDM1MDU4WjCBsDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9y +YWRvMQ8wDQYDVQQHEwZEZW52ZXIxFTATBgNVBAoTDENETi1pbi1hLUJveDEVMBMG +A1UECxMMQ0ROLWluLWEtQm94MSYwJAYDVQQDFB0qLng1MDl2MS10ZXN0Lm15Y2Ru +LmNpYWIudGVzdDEnMCUGCSqGSIb3DQEJARYYbm8tcmVwbHlAaW5mcmEuY2lhYi50 +ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzXMtRmZ4SVYpO4yf +00kKJD7MKCVzjTOKJNiOyJn++RYNX64gZU7a8LRefvruv6wO1Ic4IR7xvZ58t/sg +He6AoHW3Uz9XJ4knZ1BHNFHYsaELSDUkPNRowQprzJmAf3yDrn6kWrLVgX0iWrQh +T5UJxgS7L1iNibqAKFGkr0tRMk0rwjBzm5CGGyt1WS/J1W3h/R05BaDXukSCoSlo +cx1XgmldCQE27de+WXusITZse5h+Giei/hGkHdJJr1aROP3y+czeOF1YOr24p/0T +HPrir0iesWV2+bA/Tdj5hVWipt1OJBwOvfull9fZTvC1RRdhIyUJauWr4iwD2gpn +UI8OywIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBaEUQcKbLhlcyEE0OfcKTmHdwl +uhUpE55FkVJP9TN5nNAziYW+KRWiSyRdn/35s5Z+bFplbzT7Au5tZw6kTtkmtim3 +i6v7nNLES0hnj+zRybut4yEw9Ma0p/exiT0+qqVynBdgtpVwOcYIvgYlGgVUttNN +b/nKxOXZ9qDkqBDgMbXmYHCI5txFnqblLP8dW0CeFYIL0RuBx2qS5edYw8oTZPOL +b/CpL85+xi6pd+bOQ3UXbTaa78HEwcP1nX3IKzuMjtxUmZ5d2Gbo6TihuXiWCJHW +i/LiVIfp1/TNdiOvLRXYZV5itIKpgmr8nYCX8QRUewtP9Ex4RRcoEKQdVRpI +-----END CERTIFICATE----- +` + SelfSignedX509v1PrivateKey = ` +- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNcy1GZnhJVik7 +jJ/TSQokPswoJXONM4ok2I7Imf75Fg1friBlTtrwtF5++u6/rA7UhzghHvG9nny3 ++yAd7oCgdbdTP1cniSdnUEc0UdixoQtINSQ81GjBCmvMmYB/fIOufqRastWBfSJa +tCFPlQnGBLsvWI2JuoAoUaSvS1EyTSvCMHObkIYbK3VZL8nVbeH9HTkFoNe6RIKh +KWhzHVeCaV0JATbt175Ze6whNmx7mH4aJ6L+EaQd0kmvVpE4/fL5zN44XVg6vbin +/RMc+uKvSJ6xZXb5sD9N2PmFVaKm3U4kHA69+6WX19lO8LVFF2EjJQlq5aviLAPa +CmdQjw7LAgMBAAECggEAQUsFbIZMXCJB4GcEtEVWL8a1Y1zjqFBk6ujYF/C5E7hq +b6oLKacx9aWdEoX1Mn0gCXMf54bKFRU1VdM9lcWio1xF8vMCY9I276KXvoz0bR9d +UolxBtQKpq8FK3TtXZbY0q/0085aBFkcfe8ZVw1qmcAPLTDbapYW/LlVuVAacf16 +Ism+oVlpGosrG8pVe2nkxRLkA+FBsFNeliX8YucgvOcQWMjcJ1VPYgfA/7b8q4b7 +cVxfs7l+SrtMMYNNOM695b3AEW2Tve5JwNGEvaOJsHqS+VNHZ9T4NAr+ZAU6C237 +rM6dfPMqb/177Yvz32Bq6vbYVoeb2iDnMVbjgRQvYQKBgQD8nkXLguq+MkkhhW4c +xPYIHxZBQ948fFn1O2JKgmDR5bjQPbbXA/0Ko/l/yJ0ikNKeLC0/wXvUcQiuurIh +gFGgOU9uzaXgThZUsv35S9fiTuT4VamcQKOA42LTbxCk9O80fz4qR/mkMFz1KtoD +4cghfFRG/ZWpZ8ESSHOz8jzmJwKBgQDQM0HoBXkPZURj90jpg+oO4SD2ZTeAIfpM +YiHxI/jNV8Np8DLDne0a9ncsG1cCmPekVoEV5kliekak4H211CgWIERVOOSJumH5 +VHuqLK2BoUiEiMpAKQrG3Bc7MNK1BY8G4MUu//Sj508WJzyU1OBOHRVzc6fJ0bmK +o8EFYBg8vQKBgCufVSQYflrLqi88sFANfwLWA2zPwG+ndY1QbN+69ecpCSoEji9B +BBAzUqFLTj8qzQP9Uu8AhVahEkPB/4KjevT1EI9suakrMtX7drn269erkgSEHl7a +FqHqIiWqtzAVD717/4sjlKtSoqq/dJhZA8ssgg0kOxTe0stKcZhwSy3fAoGBAMxs +R53lIcR4DfqJZtHBcCND8PV81E2/Dt/IysLWKwiTz49JBM8FVTVQIhrwjTJDt4No +XD6AajWDEbH5qfTKZsGy1OVIgzyoAGKrDPE+BO5uyaE4Hj15DtfKahT4DysmVhTO +xU0si6wTBZge1mDb05FfBRzixjBm9+KkfnUksSeRAoGAfVxTz3PDE3oigzh3uOtu +3vB0xiUVGLsw6ZN1MJj/tkx631ejPV512uwMMTiP36zvYRgzbtNsFolz+jnfsZjp +JebgC1b0m89GkINe4oO3WGhIi7hsGGFP+CvWwQnALLX0aT+05OEbfBgoVm0ywTCf ++AQpUpVQ/mLB6W1mx9AuMeY= +-----END PRIVATE KEY----- ` CASignedRSACertificateChain = ` -----BEGIN CERTIFICATE----- @@ -752,11 +808,9 @@ igzzaBprKzbSuGpj9QKLO4P4vIvgt2RutfqYBNR6sdzKmQYyPCYshfsoQVWo9mmD jI///X8MUJs= -----END CERTIFICATE----- ` - - CASignedECDSACertificateChain = `` - CASignedECDSACertificateChainPrivateKey = `` - CASignedECDSARootCA = `` - + CASignedECDSACertificateChain = `` + CASignedECDSACertificateChainPrivateKey = `` + CASignedECDSARootCA = `` CASignedNoSkiAkiECDSACertificateChain = `` CASignedNoSkiAkiECDSACertificateChainPrivateKey = `` CASignedNoSkiAkiECDSARootCA = `` @@ -983,6 +1037,32 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairDSA(t *testing.T) { } } +func TestVerifyAndEncodeCertificateSelfSignedX509v1(t *testing.T) { + // should successfully validate as x509v1 must remain supported + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedX509v1Certificate, SelfSignedX509v1PrivateKey, "") + + if err != nil { + t.Fatalf("unexpected result: the x509v1 cert/key pair is valid and should have passed validation") + } + + if !unknownAuth { + t.Fatalf("unexpected result: certificate verification should have detected signature of unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: certChain should not be empty") + } +} + func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "") @@ -1193,7 +1273,7 @@ func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutDigit } func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPair(t *testing.T) { - // Should be successfull as the certificate and key are valid with proper keyUsage/extendedKeyUsage. + // Should be successful as the certificate and key are valid with proper keyUsage/extendedKeyUsage. _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "") if err != nil { From 8c78afe116dfb9d868822797f24be6aaaf03bb3d Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Sat, 30 Mar 2019 22:06:04 -0600 Subject: [PATCH 13/18] Remove redundant error message header. --- traffic_ops/traffic_ops_golang/deliveryservice/keys.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 3467783387..a4680c9aaf 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -66,7 +66,7 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { } certChain, certPrivateKey, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertKeyPair(req.Certificate.Crt, req.Certificate.Key, "") if err != nil { - api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("verifying certificate: "+err.Error()), nil) + api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, err, nil) return } req.Certificate.Crt = certChain From 25c407e8d7bf013bfe3b0c8dbe7dd44b0320223e Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Sun, 31 Mar 2019 12:38:57 -0600 Subject: [PATCH 14/18] Revert change, gofmt --- traffic_ops/traffic_ops_golang/deliveryservice/keys.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index a4680c9aaf..3467783387 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -66,7 +66,7 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { } certChain, certPrivateKey, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertKeyPair(req.Certificate.Crt, req.Certificate.Key, "") if err != nil { - api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, err, nil) + api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("verifying certificate: "+err.Error()), nil) return } req.Certificate.Crt = certChain From 6e8929186cf6b09d711808b41a39215439335152 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Sun, 31 Mar 2019 16:21:58 -0600 Subject: [PATCH 15/18] Use getDSType() to permit ECDSA keys for only DNS* DS types. --- .../deliveryservice/keys.go | 27 ++++++++++-- .../deliveryservice/keys_test.go | 43 ++++++++++++------- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 3467783387..9fdeee372d 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -64,7 +64,25 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr) return } - certChain, certPrivateKey, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertKeyPair(req.Certificate.Crt, req.Certificate.Key, "") + + // ECDSA keys support is only permitted for DNS delivery services + // Traffic Router (HTTP* delivery service types) do not support ECDSA keys + allowEC := false + dsType, dsFound, err := getDSType(inf.Tx.Tx, *req.Key) + if err == nil && dsFound { + switch dsType { + case tc.DSTypeDNS: + fallthrough + case tc.DSTypeDNSLive: + fallthrough + case tc.DSTypeDNSLiveNational: + allowEC = true + default: + allowEC = false + } + } + + certChain, certPrivateKey, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertKeyPair(req.Certificate.Crt, req.Certificate.Key, "", allowEC) if err != nil { api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("verifying certificate: "+err.Error()), nil) return @@ -286,7 +304,7 @@ WHERE r.pattern = $2 // indicate that the certs are signed by an unknown authority (e.g. self-signed). Otherwise, return false. // If the chain returned from Certificate.Verify() does not match the input chain, // return true. Otherwise, return false. -func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA string) (string, string, bool, bool, error) { +func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA string, allowEC bool) (string, string, bool, bool, error) { // decode, verify, and order certs for storage var cleanPemPrivateKey string = "" certs := strings.SplitAfter(pemCertificate, PemCertEndMarker) @@ -338,7 +356,10 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin case x509.ECDSA: var ecdsaPrivateKey *ecdsa.PrivateKey - // TODO - Add DNS delivery service check here. + // Only permit ECDSA support for DNS* DSTypes until the Traffic Router can support it + if !allowEC { + return "", "", false, false, errors.New("cert/key validation error: ECDSA public key algorithm unsupported for non-DNS delivery service type") + } // DSA and ECDSA is not an encryption algorithm and only a signing algorithm, hence the // certificate only needs to have the DigitalSignature KeyUsage indicated. diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index bc35d7a78a..096a414dff 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -1020,7 +1020,7 @@ func TestDecodePrivateKeyECDSAEncrypted(t *testing.T) { func TestVerifyAndEncodeCertificateBadData(t *testing.T) { // should fail bad base64 data - _, _, _, _, err := verifyCertKeyPair(BadCertData, BadKeyData, "") + _, _, _, _, err := verifyCertKeyPair(BadCertData, BadKeyData, "", true) if err == nil { t.Fatalf("unexpected result: there should have been a base64 decoding failure") } @@ -1028,7 +1028,7 @@ func TestVerifyAndEncodeCertificateBadData(t *testing.T) { func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairDSA(t *testing.T) { // should fail due to x509 + DSA being unsupported - _, _, _, _, err := verifyCertKeyPair(SelfSignedDSACertificate, SelfSignedDSAPrivateKey, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedDSACertificate, SelfSignedDSAPrivateKey, "", true) if err == nil { t.Fatalf("unexpected result: the DSA PKI algorithm is unsupported") @@ -1039,7 +1039,7 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairDSA(t *testing.T) { func TestVerifyAndEncodeCertificateSelfSignedX509v1(t *testing.T) { // should successfully validate as x509v1 must remain supported - certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedX509v1Certificate, SelfSignedX509v1PrivateKey, "") + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedX509v1Certificate, SelfSignedX509v1PrivateKey, "", true) if err != nil { t.Fatalf("unexpected result: the x509v1 cert/key pair is valid and should have passed validation") @@ -1065,7 +1065,7 @@ func TestVerifyAndEncodeCertificateSelfSignedX509v1(t *testing.T) { func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { - certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "") + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "", true) if err != nil { t.Fatalf("unexpected result: a certificate verification error should have occured") @@ -1091,7 +1091,7 @@ func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { func TestVerifyAndEncodeCertificateSelfSignedCertKeyPair(t *testing.T) { - certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedRSACertificate, SelfSignedRSAPrivateKey, "") + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedRSACertificate, SelfSignedRSAPrivateKey, "", true) if err != nil { t.Fatalf("unexpected result, a certificate verification error should have occured") @@ -1118,7 +1118,7 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPair(t *testing.T) { func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t *testing.T) { // Should fail on cert/private-key mismatch - _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificate, PrivateKeyPKCS1RSA2048, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificate, PrivateKeyPKCS1RSA2048, "", true) if err == nil { t.Fatalf("unexpected result: a certificate/key modulus mismatch error should have occurred") @@ -1130,7 +1130,7 @@ func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t * func TestVerifyAndEncodeCertificateSelfSignedNoServerAuthExtKeyUsage(t *testing.T) { // Should fail due to not having the serverAuth extKeyUsage (x509v3 only) - _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoServerAuthExtKeyUsage, SelfSignedRSAPrivateKeyNoServerAuthExtKeyUsage, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoServerAuthExtKeyUsage, SelfSignedRSAPrivateKeyNoServerAuthExtKeyUsage, "", true) if err == nil { t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the server auth extKeyUsage") @@ -1143,7 +1143,7 @@ func TestVerifyAndEncodeCertificateSelfSignedRSANoKeyEnciphermentKeyUsage(t *tes // Should fail due to not having the keyEncipherment keyUsage (x509v3 only) // keyUsage extension must include keyEncipherment if the PKI algorithm is RSA. - _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoKeyEnciphermentKeyUsage, SelfSignedRSAPrivateKeyNoKeyEnciphermentKeyUsage, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoKeyEnciphermentKeyUsage, SelfSignedRSAPrivateKeyNoKeyEnciphermentKeyUsage, "", true) if err == nil { t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the keyEncipherment keyUsage (required for x509v3+RSA certificates)") @@ -1155,7 +1155,7 @@ func TestVerifyAndEncodeCertificateSelfSignedRSANoKeyEnciphermentKeyUsage(t *tes func TestVerifyAndEncodeCertificateCASignedCertKeyPair(t *testing.T) { // Should succeed, but with unknown authority warning. - certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, "") + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, "", true) if err != nil { t.Fatalf("unexpected result: " + err.Error()) @@ -1182,7 +1182,7 @@ func TestVerifyAndEncodeCertificateCASignedCertKeyPair(t *testing.T) { func TestVerifyAndEncodeCertificateCASignedCertKeyPairWithRootCA(t *testing.T) { // should succeed and be fully validated. - certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, CASignedRSARootCA) + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, CASignedRSARootCA, true) if err != nil { t.Fatalf("unexpected result: " + err.Error()) @@ -1209,7 +1209,7 @@ func TestVerifyAndEncodeCertificateCASignedCertKeyPairWithRootCA(t *testing.T) { func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPair(t *testing.T) { // Should succeed, but with unknown authority warning. - certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, "") + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, "", true) if err != nil { t.Fatalf("unexpected result: " + err.Error()) @@ -1236,7 +1236,7 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPair(t *testing.T) { func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *testing.T) { // should succeed and be fully validated despite not having subject/authority key identifier(s). - certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, CASignedNoSkiAkiRSARootCA) + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, CASignedNoSkiAkiRSARootCA, true) if err != nil { t.Fatalf("unexpected result: " + err.Error()) @@ -1263,7 +1263,7 @@ func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *test func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutDigitalSignatureKeyUsage(t *testing.T) { // Should fail due to unsupported private/public key algorithm // keyUsage must contain the digitalSignature usage if a DSA based PKI algorithm is indicated (unlike RSA). - _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificateNoDigitalSignatureKeyUsage, SelfSignedECDSAPrivateKeyNoDigitalSignatureKeyUsage, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificateNoDigitalSignatureKeyUsage, SelfSignedECDSAPrivateKeyNoDigitalSignatureKeyUsage, "", true) if err == nil { t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the digitalSignature keyUsage (required for x509v3+ECDSA certificates)") @@ -1274,16 +1274,27 @@ func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutDigit func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPair(t *testing.T) { // Should be successful as the certificate and key are valid with proper keyUsage/extendedKeyUsage. - _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "", true) if err != nil { t.Fatalf("unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) } } +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairECDisabled(t *testing.T) { + // Should be rejected as allowEC flag has been set to false + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "", false) + + if err == nil { + t.Fatalf("unexpected result - ECDSA cert/key pair should have been rejected due to allowEC being false") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutParams(t *testing.T) { // Test result should be successful as the certificate and key are valid with proper keyUsage/extendedKeyUsage. - _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKeyWithoutParams, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKeyWithoutParams, "", true) if err != nil { t.Fatalf("unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) @@ -1292,7 +1303,7 @@ func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutParam func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairMisMatchedPrivateKey(t *testing.T) { // Should fail due to mismatched ECDSA cert/private key pair - _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, PrivateKeyECDSANISTPrime256V1, "") + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, PrivateKeyECDSANISTPrime256V1, "", true) if err == nil { t.Fatalf("unexpected Result: Mismatched ECDSA cert/key pair should have failed verification") From 318dfd550397a4184471a58890f317c7bf545687 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Tue, 2 Apr 2019 10:55:33 -0600 Subject: [PATCH 16/18] Update tc.DSType.IsDNS() method to only include DNS DS types. --- lib/go-tc/enum.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/go-tc/enum.go b/lib/go-tc/enum.go index de7a4add7c..ce1e4fb893 100644 --- a/lib/go-tc/enum.go +++ b/lib/go-tc/enum.go @@ -495,8 +495,6 @@ func (t DSType) IsHTTP() bool { // IsDNS returns whether the DSType is a DNS category. func (t DSType) IsDNS() bool { switch t { - case DSTypeHTTPNoCache: - fallthrough case DSTypeDNS: fallthrough case DSTypeDNSLive: From e6e80d51a82a9e66b083111ed0cec1942e9ca747 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Tue, 2 Apr 2019 11:27:12 -0600 Subject: [PATCH 17/18] Use updated tc.DSType.isDNS() method to determine if DS is a DNS type. --- .../traffic_ops_golang/deliveryservice/keys.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 9fdeee372d..b82d3eb69e 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -67,19 +67,10 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { // ECDSA keys support is only permitted for DNS delivery services // Traffic Router (HTTP* delivery service types) do not support ECDSA keys - allowEC := false dsType, dsFound, err := getDSType(inf.Tx.Tx, *req.Key) - if err == nil && dsFound { - switch dsType { - case tc.DSTypeDNS: - fallthrough - case tc.DSTypeDNSLive: - fallthrough - case tc.DSTypeDNSLiveNational: - allowEC = true - default: - allowEC = false - } + allowEC := false + if err == nil && dsFound && dsType.IsDNS() { + allowEC = true } certChain, certPrivateKey, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertKeyPair(req.Certificate.Crt, req.Certificate.Key, "", allowEC) From fc09c4200304c003de9f84805e63459a2ca4b8b2 Mon Sep 17 00:00:00 2001 From: Jeffrey Bevill Date: Tue, 2 Apr 2019 11:59:47 -0600 Subject: [PATCH 18/18] Check errors returned from rsa/ecdsa private key decoding methods Minor changes to error message formatting and string comparison Re-sort go import statements --- .../deliveryservice/keys.go | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index b82d3eb69e..2923b41845 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -29,11 +29,11 @@ import ( "encoding/pem" "errors" "fmt" - "github.com/apache/trafficcontrol/lib/go-util" "net/http" "strings" "github.com/apache/trafficcontrol/lib/go-tc" + "github.com/apache/trafficcontrol/lib/go-util" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant" @@ -297,7 +297,7 @@ WHERE r.pattern = $2 // return true. Otherwise, return false. func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA string, allowEC bool) (string, string, bool, bool, error) { // decode, verify, and order certs for storage - var cleanPemPrivateKey string = "" + cleanPemPrivateKey := "" certs := strings.SplitAfter(pemCertificate, PemCertEndMarker) if len(certs) <= 1 { return "", "", false, false, errors.New("no certificate chain to verify") @@ -330,15 +330,18 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin return "", "", false, false, errors.New("cert/key (rsa) validation: no keyEncipherment keyUsage extension present in x509v3 server certificate") } - // Attempt to decode the RSA private key - rsaPrivateKey, cleanPemPrivateKey, err = decodeRSAPrivateKey(pemPrivateKey) - // Extract the RSA public key from the x509 certificate certPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) if !ok || certPublicKey == nil { return "", "", false, false, errors.New("cert/key (rsa) validation error: could not extract public RSA key from certificate") } + // Attempt to decode the RSA private key + rsaPrivateKey, cleanPemPrivateKey, err = decodeRSAPrivateKey(pemPrivateKey) + if err != nil { + return "", "", false, false, err + } + // Check RSA private key modulus against the x509 RSA public key modulus if rsaPrivateKey != nil && certPublicKey != nil && !bytes.Equal(rsaPrivateKey.N.Bytes(), certPublicKey.N.Bytes()) { return "", "", false, false, errors.New("cert/key (rsa) mismatch error: RSA public N modulus value mismatch") @@ -360,6 +363,9 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin // Attempt to decode the ECDSA private key ecdsaPrivateKey, cleanPemPrivateKey, err = decodeECDSAPrivateKey(pemPrivateKey) + if err != nil { + return "", "", false, false, err + } // Extract the ECDSA public key from the x509 certificate certPublicKey, ok := cert.PublicKey.(*ecdsa.PublicKey) @@ -368,7 +374,7 @@ func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA strin } // Compare the ECDSA curve name contained within the x509.PublicKey against the curve name indicated in the private key - if strings.Compare(certPublicKey.Params().Name, ecdsaPrivateKey.Params().Name) != 0 { + if certPublicKey.Params().Name != ecdsaPrivateKey.Params().Name { return "", "", false, false, errors.New("cert/key (ecdsa) mismatch error: ECDSA curve name in cert does not match curve name in private key") } @@ -538,15 +544,13 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Decode PKCS#8 - RSA Private Key privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - msg := fmt.Sprintf("private key validation error: parse pkcs#8 error - %s", err.Error()) - decodeErrors = append(decodeErrors, errors.New(msg)) + decodeErrors = append(decodeErrors, errors.New("private key validation error: parse pkcs#8 error: "+err.Error())) } // Determine if the privateKey is of the correct type rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey) if !ok || rsaPrivateKey == nil { - msg := fmt.Sprintf("private key validation error: incorrect private key type - %T", privateKey) - decodeErrors = append(decodeErrors, errors.New(msg)) + decodeErrors = append(decodeErrors, fmt.Errorf("private key validation error: incorrect private key type: %T", privateKey)) } else { return rsaPrivateKey, trimmedPrivateKey, nil } @@ -554,8 +558,7 @@ func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) // Decode PKCS#1 - RSA Private Key rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil || rsaPrivateKey == nil { - msg := fmt.Sprintf("private key validation error: parse pkcs#1 error: %s", err.Error()) - decodeErrors = append(decodeErrors, errors.New(msg)) + decodeErrors = append(decodeErrors, errors.New("private key validation error: parse pkcs#1 error: "+err.Error())) return nil, "", util.JoinErrsSep(decodeErrors, ", ") } @@ -619,8 +622,7 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // First try to parse an EC key the normal way, before attempting PKCS8 ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes) if ecdsaPrivateKey == nil || err != nil { - msg := fmt.Sprintf("private key validation error: failed to parse EC ANSI X9.62 - %s", err.Error()) - decodeErrors = append(decodeErrors, errors.New(msg)) + decodeErrors = append(decodeErrors, errors.New("private key validation error: failed to parse EC ANSI X9.62: "+err.Error())) } else { return ecdsaPrivateKey, trimmedPrivateKey, nil } @@ -628,16 +630,14 @@ func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, err // Second, try to parse PEM block as a PKCS#8 formatted RSA Private Key. privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - msg := fmt.Sprintf("private key validation error: parse pkcs#8 error - %s", err.Error()) - decodeErrors = append(decodeErrors, errors.New(msg)) + decodeErrors = append(decodeErrors, errors.New("private key validation error: parse pkcs#8 error: %s"+err.Error())) return nil, "", util.JoinErrsSep(decodeErrors, ", ") } // Make sure the privateKey is of the correct type (ecdsa.PrivateKey) ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) if !ok || ecdsaPrivateKey == nil { - msg := fmt.Sprintf("private key validation error: incorrect private key type - %T", privateKey) - decodeErrors = append(decodeErrors, errors.New(msg)) + decodeErrors = append(decodeErrors, fmt.Errorf("private key validation error: incorrect private key type: %T", privateKey)) return nil, "", util.JoinErrsSep(decodeErrors, ", ") }