From 622a2083afc0107fb46d33586a3b5611cbadf932 Mon Sep 17 00:00:00 2001 From: Danny Halawi Date: Mon, 24 Aug 2020 18:18:49 +0000 Subject: [PATCH 1/5] adding mutated cert chain --- proto/asn1-pdu/mutated_x509_chain.proto | 57 +++++++++++++++ proto/asn1-pdu/mutated_x509_chain_to_der.cc | 79 +++++++++++++++++++++ proto/asn1-pdu/mutated_x509_chain_to_der.h | 47 ++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 proto/asn1-pdu/mutated_x509_chain.proto create mode 100644 proto/asn1-pdu/mutated_x509_chain_to_der.cc create mode 100644 proto/asn1-pdu/mutated_x509_chain_to_der.h diff --git a/proto/asn1-pdu/mutated_x509_chain.proto b/proto/asn1-pdu/mutated_x509_chain.proto new file mode 100644 index 0000000..40b4353 --- /dev/null +++ b/proto/asn1-pdu/mutated_x509_chain.proto @@ -0,0 +1,57 @@ +// Copyright 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +// This protobuf represents an X.509 certificate chain with a set of operations +// to mutate the chain to create structural relationships between the +// certificates. + +syntax = "proto2"; + +import "x509_certificate.proto"; + +package mutated_x509_chain; + +message MutatedX509Chain { + required X509Chain x509_chain = 1; + repeated Operation operations = 2; +} + +// An X.509 Certificate Chain comprises a list of |certificates|. +message X509Chain { + repeated x509_certificate.X509Certificate certificates = 1; +} + +message Operation { + oneof types { + MutateSignatureOperation mutate_signature_operation = 1; + } + // |index| represents the position of the certificate that will be mutated. + required CertIndex index = 2; +} + +message MutateSignatureOperation { + // Allow certificate to be valid or invalid for fuzzing. + required bool is_valid = 1; +} + +// Contains the positions of the certiciate chain that will be mutated. +enum CertIndex { + pos_0 = 0; + pos_1 = 1; + pos_2 = 2; + pos_3 = 3; + pos_4 = 4; +} \ No newline at end of file diff --git a/proto/asn1-pdu/mutated_x509_chain_to_der.cc b/proto/asn1-pdu/mutated_x509_chain_to_der.cc new file mode 100644 index 0000000..5df0bd2 --- /dev/null +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.cc @@ -0,0 +1,79 @@ +// Copyright 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include "mutated_x509_chain_to_der.h" +#include "x509_certificate_to_der.h" + +namespace mutated_x509_chain { + +std::vector> EncodeX509Chain(const X509Chain& x509_chain) { + std::vector> der; + + for (const auto& cert : x509_chain.certificates()) { + der.push_back(X509CertificateToDER(cert)); + } + + return der; +} + +DECLARE_APPLY_OPERATION_FUNCTION(MutateSignatureOperation) { + auto* signature_value = x509.mutable_signature_value(); + signature_value->clear_pdu(); + signature_value->mutable_value()->set_unused_bits( + asn1_universal_types::UnusedBits::VAL0); + // Represent a valid signature value with 1 and invalid with 0. + if (operation.is_valid()) { + signature_value->mutable_value()->set_val("1"); + } else { + signature_value->mutable_value()->set_val("0"); + } +} + +DECLARE_APPLY_OPERATION_FUNCTION(Operation) { + switch (operation.types_case()) { + case Operation::TypesCase::kMutateSignatureOperation: + ApplyOperation(x509, operation.mutate_signature_operation()); + break; + case Operation::TypesCase::TYPES_NOT_SET: + return; + } +} + +// An |index| of a certiciate is valid if it's less than the |size| of the +// certificate chain. +inline bool isValidIndex(uint8_t index, size_t size) { + return index < size; +} + +std::vector> MutatedChainToDER( + const MutatedX509Chain& mutated_x509_chain) { + auto x509_chain = mutated_x509_chain.x509_chain().certificates(); + auto operations = mutated_x509_chain.operations(); + + if (x509_chain.empty()) { + return {{}}; + } + + for (const auto& operation : operations) { + if (isValidIndex(operation.index(), x509_chain.size())) { + ApplyOperation(x509_chain[operation.index()], operation); + } + } + + return EncodeX509Chain(mutated_x509_chain.x509_chain()); +} + +} // namespace mutated_x509_chain \ No newline at end of file diff --git a/proto/asn1-pdu/mutated_x509_chain_to_der.h b/proto/asn1-pdu/mutated_x509_chain_to_der.h new file mode 100644 index 0000000..cf86d97 --- /dev/null +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.h @@ -0,0 +1,47 @@ +// Copyright 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef PROTO_ASN1_PDU_MUTATE_X509_CHAIN_H_ +#define PROTO_ASN1_PDU_MUTATE_X509_CHAIN_H_ + +#include + +#include + +#include "mutated_x509_chain.pb.h" + +namespace mutated_x509_chain { + +// Applies |operations| to |x509_chain| and returns the DER encoded chain. +std::vector> MutatedChainToDER( + const MutatedX509Chain& mutated_x509_chain); + +// Applies the |TYPE| operation to |x509| in order to create meaningful +// certificate chains. +#define DECLARE_APPLY_OPERATION_FUNCTION(TYPE) \ + void ApplyOperation(x509_certificate::X509Certificate& x509, \ + const TYPE& operation) + +DECLARE_APPLY_OPERATION_FUNCTION(Operation); +DECLARE_APPLY_OPERATION_FUNCTION(MutateSignatureOperation); + +// DER encodes each |certificate| in |x509_chain| and returns +// the encoded certificates in |der|. +std::vector> EncodeX509Chain(const X509Chain& x509_chain); + +} // namespace mutated_x509_chain + +#endif // PROTO_ASN1_PDU_X509_CERTIFICATE_TO_DER_H_ \ No newline at end of file From 235de60a66826198bf5dda26945b0fa9e37be07a Mon Sep 17 00:00:00 2001 From: Danny Halawi Date: Mon, 24 Aug 2020 18:24:02 +0000 Subject: [PATCH 2/5] taking out unneeded include --- proto/asn1-pdu/mutated_x509_chain_to_der.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/proto/asn1-pdu/mutated_x509_chain_to_der.cc b/proto/asn1-pdu/mutated_x509_chain_to_der.cc index 5df0bd2..e99cadd 100644 --- a/proto/asn1-pdu/mutated_x509_chain_to_der.cc +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.cc @@ -15,7 +15,6 @@ //////////////////////////////////////////////////////////////////////////////// #include "mutated_x509_chain_to_der.h" -#include "x509_certificate_to_der.h" namespace mutated_x509_chain { From aac2cf0990cc3066b8b2425ccf8e0cd72e6d8ae7 Mon Sep 17 00:00:00 2001 From: Danny Halawi Date: Mon, 24 Aug 2020 21:27:00 +0000 Subject: [PATCH 3/5] refactor --- proto/asn1-pdu/mutated_x509_chain.proto | 30 ++++++------ proto/asn1-pdu/mutated_x509_chain_to_der.cc | 53 ++++++++++++--------- proto/asn1-pdu/mutated_x509_chain_to_der.h | 19 ++------ 3 files changed, 47 insertions(+), 55 deletions(-) diff --git a/proto/asn1-pdu/mutated_x509_chain.proto b/proto/asn1-pdu/mutated_x509_chain.proto index 40b4353..7275ce3 100644 --- a/proto/asn1-pdu/mutated_x509_chain.proto +++ b/proto/asn1-pdu/mutated_x509_chain.proto @@ -22,36 +22,34 @@ syntax = "proto2"; import "x509_certificate.proto"; -package mutated_x509_chain; +package x509_certificate; -message MutatedX509Chain { - required X509Chain x509_chain = 1; +message MutatedChain { + // An X.509 Certificate Chain comprises a list of certificates. + repeated x509_certificate.X509Certificate chain = 1; repeated Operation operations = 2; } -// An X.509 Certificate Chain comprises a list of |certificates|. -message X509Chain { - repeated x509_certificate.X509Certificate certificates = 1; -} - +// Operations to mutate the certificate chain to force structural relationships +// between the certificates. message Operation { oneof types { MutateSignatureOperation mutate_signature_operation = 1; } - // |index| represents the position of the certificate that will be mutated. - required CertIndex index = 2; } message MutateSignatureOperation { // Allow certificate to be valid or invalid for fuzzing. - required bool is_valid = 1; + required bool valid = 1; + // |index| represents the position of the certificate that will be mutated. + required CertIndex index = 2; } // Contains the positions of the certiciate chain that will be mutated. enum CertIndex { - pos_0 = 0; - pos_1 = 1; - pos_2 = 2; - pos_3 = 3; - pos_4 = 4; + CERT_0 = 0; + CERT_1 = 1; + CERT_2 = 2; + CERT_3 = 3; + CERT_4 = 4; } \ No newline at end of file diff --git a/proto/asn1-pdu/mutated_x509_chain_to_der.cc b/proto/asn1-pdu/mutated_x509_chain_to_der.cc index e99cadd..55c0b20 100644 --- a/proto/asn1-pdu/mutated_x509_chain_to_der.cc +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.cc @@ -15,64 +15,71 @@ //////////////////////////////////////////////////////////////////////////////// #include "mutated_x509_chain_to_der.h" +#include "x509_certificate_to_der.h" -namespace mutated_x509_chain { +namespace x509_certificate { -std::vector> EncodeX509Chain(const X509Chain& x509_chain) { +// DER encodes each |certificate| in |chain| and returns +// the encoded certificates in |der|. +std::vector> EncodeChain( + const google::protobuf::RepeatedPtrField& chain) { std::vector> der; - for (const auto& cert : x509_chain.certificates()) { + for (const auto& cert : chain) { der.push_back(X509CertificateToDER(cert)); } return der; } -DECLARE_APPLY_OPERATION_FUNCTION(MutateSignatureOperation) { - auto* signature_value = x509.mutable_signature_value(); +void ApplyOperation( + const MutateSignatureOperation& operation, + google::protobuf::RepeatedPtrField& chain) { + // An |operation| on a certiciate cannot be executed if the |index| is greater + // than or euqal to the |size| of the certificate chain. + if (operation.index() >= chain.size()) { + return; + } + + auto* signature_value = + chain[operation.index()].mutable_signature_value(); signature_value->clear_pdu(); signature_value->mutable_value()->set_unused_bits( asn1_universal_types::UnusedBits::VAL0); // Represent a valid signature value with 1 and invalid with 0. - if (operation.is_valid()) { + if (operation.valid()) { signature_value->mutable_value()->set_val("1"); } else { signature_value->mutable_value()->set_val("0"); } } -DECLARE_APPLY_OPERATION_FUNCTION(Operation) { +void ApplyOperation( + const Operation& operation, + google::protobuf::RepeatedPtrField& chain) { switch (operation.types_case()) { case Operation::TypesCase::kMutateSignatureOperation: - ApplyOperation(x509, operation.mutate_signature_operation()); + ApplyOperation(operation.mutate_signature_operation(), chain); break; case Operation::TypesCase::TYPES_NOT_SET: return; } } -// An |index| of a certiciate is valid if it's less than the |size| of the -// certificate chain. -inline bool isValidIndex(uint8_t index, size_t size) { - return index < size; -} - std::vector> MutatedChainToDER( - const MutatedX509Chain& mutated_x509_chain) { - auto x509_chain = mutated_x509_chain.x509_chain().certificates(); - auto operations = mutated_x509_chain.operations(); + const MutatedChain& mutated_chain) { + auto chain = mutated_chain.chain(); + auto operations = mutated_chain.operations(); - if (x509_chain.empty()) { + if (chain.empty()) { return {{}}; } for (const auto& operation : operations) { - if (isValidIndex(operation.index(), x509_chain.size())) { - ApplyOperation(x509_chain[operation.index()], operation); - } + ApplyOperation(operation, chain); } - return EncodeX509Chain(mutated_x509_chain.x509_chain()); + return EncodeChain(chain); } -} // namespace mutated_x509_chain \ No newline at end of file +} // namespace x509_certificate \ No newline at end of file diff --git a/proto/asn1-pdu/mutated_x509_chain_to_der.h b/proto/asn1-pdu/mutated_x509_chain_to_der.h index cf86d97..a89bfdd 100644 --- a/proto/asn1-pdu/mutated_x509_chain_to_der.h +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.h @@ -23,25 +23,12 @@ #include "mutated_x509_chain.pb.h" -namespace mutated_x509_chain { +namespace x509_certificate { // Applies |operations| to |x509_chain| and returns the DER encoded chain. std::vector> MutatedChainToDER( - const MutatedX509Chain& mutated_x509_chain); + const MutatedChain& mutated_chain); -// Applies the |TYPE| operation to |x509| in order to create meaningful -// certificate chains. -#define DECLARE_APPLY_OPERATION_FUNCTION(TYPE) \ - void ApplyOperation(x509_certificate::X509Certificate& x509, \ - const TYPE& operation) - -DECLARE_APPLY_OPERATION_FUNCTION(Operation); -DECLARE_APPLY_OPERATION_FUNCTION(MutateSignatureOperation); - -// DER encodes each |certificate| in |x509_chain| and returns -// the encoded certificates in |der|. -std::vector> EncodeX509Chain(const X509Chain& x509_chain); - -} // namespace mutated_x509_chain +} // namespace x509_certificate #endif // PROTO_ASN1_PDU_X509_CERTIFICATE_TO_DER_H_ \ No newline at end of file From 3d12f48b369b7c429caf7a4d04597efec952eed9 Mon Sep 17 00:00:00 2001 From: Danny Halawi Date: Mon, 24 Aug 2020 21:32:06 +0000 Subject: [PATCH 4/5] improving comments and naming --- proto/asn1-pdu/mutated_x509_chain.proto | 11 ++++++----- proto/asn1-pdu/mutated_x509_chain_to_der.cc | 4 ++-- proto/asn1-pdu/mutated_x509_chain_to_der.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/proto/asn1-pdu/mutated_x509_chain.proto b/proto/asn1-pdu/mutated_x509_chain.proto index 7275ce3..7471e3d 100644 --- a/proto/asn1-pdu/mutated_x509_chain.proto +++ b/proto/asn1-pdu/mutated_x509_chain.proto @@ -25,13 +25,13 @@ import "x509_certificate.proto"; package x509_certificate; message MutatedChain { - // An X.509 Certificate Chain comprises a list of certificates. + // An certificate chain comprises a list of certificates. repeated x509_certificate.X509Certificate chain = 1; repeated Operation operations = 2; } -// Operations to mutate the certificate chain to force structural relationships -// between the certificates. +// Operation is used to mutate the certificate chain to force structural +// relationships between the certificates. message Operation { oneof types { MutateSignatureOperation mutate_signature_operation = 1; @@ -41,11 +41,12 @@ message Operation { message MutateSignatureOperation { // Allow certificate to be valid or invalid for fuzzing. required bool valid = 1; - // |index| represents the position of the certificate that will be mutated. + // |index| represents the position of the certificate whose signature will be + // mutated. required CertIndex index = 2; } -// Contains the positions of the certiciate chain that will be mutated. +// Contains the positions of the certiciate chain that can be mutated. enum CertIndex { CERT_0 = 0; CERT_1 = 1; diff --git a/proto/asn1-pdu/mutated_x509_chain_to_der.cc b/proto/asn1-pdu/mutated_x509_chain_to_der.cc index 55c0b20..c6ca06c 100644 --- a/proto/asn1-pdu/mutated_x509_chain_to_der.cc +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.cc @@ -41,8 +41,7 @@ void ApplyOperation( return; } - auto* signature_value = - chain[operation.index()].mutable_signature_value(); + auto* signature_value = chain[operation.index()].mutable_signature_value(); signature_value->clear_pdu(); signature_value->mutable_value()->set_unused_bits( asn1_universal_types::UnusedBits::VAL0); @@ -71,6 +70,7 @@ std::vector> MutatedChainToDER( auto chain = mutated_chain.chain(); auto operations = mutated_chain.operations(); + // If the chain is empty, return immediately to not slow down the fuzzer. if (chain.empty()) { return {{}}; } diff --git a/proto/asn1-pdu/mutated_x509_chain_to_der.h b/proto/asn1-pdu/mutated_x509_chain_to_der.h index a89bfdd..9ae6664 100644 --- a/proto/asn1-pdu/mutated_x509_chain_to_der.h +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.h @@ -25,7 +25,7 @@ namespace x509_certificate { -// Applies |operations| to |x509_chain| and returns the DER encoded chain. +// Applies |operations| to |chain| and returns the DER encoded chain. std::vector> MutatedChainToDER( const MutatedChain& mutated_chain); From 756fa29e95bd750a492ebd614cb82c01e5dba548 Mon Sep 17 00:00:00 2001 From: Danny Halawi Date: Mon, 24 Aug 2020 21:33:00 +0000 Subject: [PATCH 5/5] nit: an -> a --- proto/asn1-pdu/mutated_x509_chain.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/asn1-pdu/mutated_x509_chain.proto b/proto/asn1-pdu/mutated_x509_chain.proto index 7471e3d..63b7963 100644 --- a/proto/asn1-pdu/mutated_x509_chain.proto +++ b/proto/asn1-pdu/mutated_x509_chain.proto @@ -25,7 +25,7 @@ import "x509_certificate.proto"; package x509_certificate; message MutatedChain { - // An certificate chain comprises a list of certificates. + // A certificate chain comprises a list of certificates. repeated x509_certificate.X509Certificate chain = 1; repeated Operation operations = 2; }