Skip to content

Commit a3c3628

Browse files
author
Jean-Romain Garnier
committed
Add X509 encoding test
1 parent a01c196 commit a3c3628

File tree

8 files changed

+162
-0
lines changed

8 files changed

+162
-0
lines changed

proto/asn1-pdu/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
*.py
2+
*.pyc
3+
__pycache__
4+
5+
*.pb.h
6+
*.pb.cc
7+
*.o

proto/asn1-pdu/Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
LPM_DIR=../../../libprotobuf-mutator
2+
PROTOBUF_DIR=$(LPM_DIR)/build/external.protobuf
3+
FLAGS=-O2 -Wall -Wextra -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fstack-clash-protection -fPIE -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,separate-code
4+
5+
all: proto cpp
6+
7+
proto: *.proto
8+
protoc *.proto --python_out=. --cpp_out=.
9+
10+
cpp: *.h *.cc
11+
$(CXX) -c $(FLAGS) *.cc -I$(LPM_DIR) -I$(PROTOBUF_DIR)/include
12+
13+
clean:
14+
$(RM) *.o

proto/tests/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.py
2+
*.pyc
3+
*.pem
4+
*.der
5+
*.proto

proto/tests/Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
LPM_DIR=../../../libprotobuf-mutator
2+
PROTOBUF_DIR=$(LPM_DIR)/build/external.protobuf
3+
ASN1_PROTOBUF_DIR=../asn1-pdu
4+
FLAGS=-O2 -Wall -Wextra -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fstack-clash-protection -fPIE -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,separate-code
5+
6+
all: protobuf tests
7+
8+
protobuf:
9+
$(MAKE) -C $(ASN1_PROTOBUF_DIR) all
10+
11+
tests: protobuf_to_der.cpp
12+
$(CXX) $(FLAGS) -o protobuf_to_der.o protobuf_to_der.cpp $(ASN1_PROTOBUF_DIR)/*.o -I$(PROTOBUF_DIR)/include -I$(LPM_DIR) -I$(ASN1_PROTOBUF_DIR) $(LPM_DIR)/build/src/libfuzzer/libprotobuf-mutator-libfuzzer.a $(LPM_DIR)/build/src/libprotobuf-mutator.a $(PROTOBUF_DIR)/lib/libprotobuf.a -lcrypto
13+
14+
clean:
15+
$(RM) *.o
16+
$(MAKE) -C $(ASN1_PROTOBUF_DIR) clean

proto/tests/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Proto tests
2+
3+
## Setup
4+
5+
Clone and build `libprotobuf-mutator`:
6+
7+
```sh
8+
$ git clone https://github.com/google/libprotobuf-mutator.git libprotobuf-mutator
9+
$ cd libprotobuf-mutator
10+
$ mkdir build && cd build
11+
$ cmake .. -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release
12+
$ ninja
13+
```
14+
15+
Clone `google-fuzzing` and build test files:
16+
17+
```
18+
$ git clone https://github.com/google/fuzzing.git fuzzing
19+
$ cd fuzzing/proto/tests
20+
$ make
21+
```
22+
23+
## Run
24+
25+
Generate python files:
26+
27+
```sh
28+
$ protoc ../asn1-pdu/*.proto --python_out=../asn1-pdu
29+
```
30+
31+
Generate a test certificate and convert it to the DER format:
32+
33+
```sh
34+
$ openssl req -nodes -new -x509 -keyout key.pem -out cert.pem
35+
$ openssl x509 -in cert.pem -out cert.der -outform DER
36+
```
37+
38+
Convert it to protobuf:
39+
40+
```sh
41+
$ ./x509_to_protobuf.py cert.pem cert.proto
42+
```
43+
44+
Convert the protobuf back to DER:
45+
46+
```sh
47+
$ ./protobuf_to_der.o cert.proto cert-2.der
48+
```
49+
50+
Make sure OpenSSL can properly parse the certificate and compare it to the
51+
initial one:
52+
53+
```
54+
$ openssl x509 -inform DER -in cert-2.der -noout -text
55+
$ openssl x509 -inform DER -in cert.der -noout -text
56+
```

proto/tests/protobuf_to_der.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <fstream>
2+
#include <openssl/evp.h>
3+
#include "x509_certificate.pb.h"
4+
5+
#include "asn1_pdu_to_der.h"
6+
#include "x509_certificate_to_der.h"
7+
8+
std::string base64_encode(const unsigned char *buf, int len) {
9+
const auto expected_size = 4 * ((len + 2) / 3);
10+
auto output = reinterpret_cast<char *>(calloc(expected_size + 1, 1));
11+
const auto actual_size = EVP_EncodeBlock(reinterpret_cast<unsigned char *>(output), buf, len);
12+
if (expected_size != actual_size) {
13+
std::cerr << "Wrong base64 output length: expected " << expected_size << " but got " << actual_size << ".\n";
14+
}
15+
return output;
16+
}
17+
18+
std::string readFile(const char* path) {
19+
printf("Reading file at %s\n", path);
20+
std::ifstream file(path, std::ios::in | std::ios::binary);
21+
std::string str = std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
22+
printf("Read %ld bytes\n\n", str.length());
23+
return str;
24+
}
25+
26+
void writeFile(const char* path, std::vector<uint8_t> data) {
27+
printf("Writing %ld bytes to %s\n", data.size(), path);
28+
std::ofstream file(path, std::ios::out | std::ios::binary);
29+
std::copy(data.begin(), data.end(), std::ostreambuf_iterator<char>(file));
30+
}
31+
32+
int main(int argc, char **argv) {
33+
if (argc != 3) {
34+
printf("Usage: ./protobuf_to_der.o <in file> <out file>\n");
35+
return 1;
36+
}
37+
38+
std::string protobuf = readFile(argv[1]);
39+
std::string b64Protobuf = base64_encode((unsigned char *)protobuf.c_str(), protobuf.length());
40+
printf("Protobuf: %s\n\n", b64Protobuf.c_str());
41+
42+
x509_certificate::X509Certificate input;
43+
bool parse_ok = input.ParseFromArray(protobuf.c_str(), protobuf.length());
44+
if (!parse_ok) {
45+
printf("ParseFromArray failed!\n");
46+
return 1;
47+
}
48+
49+
std::string serialized;
50+
input.SerializeToString(&serialized);
51+
std::string b64Serialized = base64_encode((unsigned char *)serialized.c_str(), serialized.length());
52+
printf("Re-serialized protobuf: %s\n\n", b64Serialized.c_str());
53+
54+
std::vector<uint8_t> asn1 = x509_certificate::X509CertificateToDER(input);
55+
56+
std::string b64asn1 = base64_encode(asn1.data(), asn1.size());
57+
printf("ASN.1: %s\n", b64asn1.c_str());
58+
59+
writeFile(argv[2], asn1);
60+
61+
return 0;
62+
}

proto/tests/protobuf_to_der.o

2.13 MB
Binary file not shown.

proto/tests/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
asn1crypto
2+
protobuf

0 commit comments

Comments
 (0)