diff --git a/proto/asn1-pdu/mutated_x509_chain.proto b/proto/asn1-pdu/mutated_x509_chain.proto new file mode 100644 index 0000000..cd5c70c --- /dev/null +++ b/proto/asn1-pdu/mutated_x509_chain.proto @@ -0,0 +1,63 @@ +// 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 x509_certificate; + +message MutatedChain { + // An X.509 Certificate Chain comprises a list of certificates. + repeated x509_certificate.X509Certificate chain = 1; + repeated TrustParameter trust_parameters = 2; + repeated Mutation mutations = 3; +} + +message TrustParameter { + // Allow certificate to be trusted or not-trusted. + required bool trusted = 1; + // |index| represents the position of the certificate that will be mutated. + required CertIndex index = 2; +} + +// Mutate the certificate chain protobuf to force structural relationships +// between the certificates. +message Mutation { + oneof types { + MutateSignature mutate_signature = 1; + } +} + +message MutateSignature { + // Allow certificate to be valid or invalid for fuzzing. + 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 { + 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 new file mode 100644 index 0000000..50f5d3e --- /dev/null +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.cc @@ -0,0 +1,106 @@ +// 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" + +#include + +#include +#include + +namespace x509_certificate { + +// 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 : chain) { + der.push_back(X509CertificateToDER(cert)); + } + + return der; +} + +void SetTrust( + std::vector& encoded_mutated_chain, + google::protobuf::RepeatedPtrField& trust_parameters) { + for (const auto& trust_parameter : trust_parameters) { + if (trust_parameter.index() >= encoded_mutated_chain.size()) { + continue; + } + + encoded_mutated_chain[trust_parameter.index()].trusted = + trust_parameter.trusted(); + } +} + +void Mutate(const MutateSignature& mutation, + 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 (mutation.index() >= chain.size()) { + return; + } + + auto* signature_value = chain[mutation.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 (mutation.valid()) { + signature_value->mutable_value()->set_val("1"); + } else { + signature_value->mutable_value()->set_val("0"); + } +} + +void Mutate(const Mutation& mutation, + google::protobuf::RepeatedPtrField& chain) { + switch (mutation.types_case()) { + case Mutation::TypesCase::kMutateSignature: + Mutate(mutation.mutate_signature(), chain); + break; + case Mutation::TypesCase::TYPES_NOT_SET: + return; + } +} + +std::vector MutatedChainToDER(const MutatedChain& mutated_chain) { + auto chain = mutated_chain.chain(); + auto trust_parameters = mutated_chain.trust_parameters(); + auto mutations = mutated_chain.mutations(); + + if (chain.empty()) { + return {{}}; + } + + for (const auto& mutation : mutations) { + Mutate(mutation, chain); + } + + std::vector encoded_mutated_chain; + for (const auto& encoded_cert : EncodeChain(chain)) { + encoded_mutated_chain.push_back({encoded_cert, false}); + } + SetTrust(encoded_mutated_chain, trust_parameters); + + return encoded_mutated_chain; +} + +} // 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 new file mode 100644 index 0000000..49ec616 --- /dev/null +++ b/proto/asn1-pdu/mutated_x509_chain_to_der.h @@ -0,0 +1,38 @@ +// 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 x509_certificate { + +struct X509 { + std::vector cert; + bool trusted; +}; + +// Applies |operations| to |x509_chain| and returns the DER encoded chain. +std::vector MutatedChainToDER(const MutatedChain& mutated_chain); + +} // namespace x509_certificate + +#endif // PROTO_ASN1_PDU_X509_CERTIFICATE_TO_DER_H_ \ No newline at end of file