Skip to content

Commit 680f199

Browse files
committed
Add module circl
1 parent a01e030 commit 680f199

File tree

7 files changed

+384
-0
lines changed

7 files changed

+384
-0
lines changed

entry.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,10 @@
317317
#include <modules/v8/module.h>
318318
#endif
319319

320+
#if defined(CRYPTOFUZZ_CIRCL)
321+
#include <modules/circl/module.h>
322+
#endif
323+
320324
std::shared_ptr<cryptofuzz::Driver> driver = nullptr;
321325

322326
const cryptofuzz::Options* cryptofuzz_options = nullptr;
@@ -641,6 +645,10 @@ extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
641645
driver->LoadModule( std::make_shared<cryptofuzz::module::V8>() );
642646
#endif
643647

648+
#if defined(CRYPTOFUZZ_CIRCL)
649+
driver->LoadModule( std::make_shared<cryptofuzz::module::circl>() );
650+
#endif
651+
644652
/* TODO check if options.forceModule (if set) refers to a module that is
645653
* actually loaded, warn otherwise.
646654
*/

gen_repository.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ def getTableEntryList(self, index):
306306
modules.Add( Module("bn.js") )
307307
modules.Add( Module("chia_bls") )
308308
modules.Add( Module("cifra") )
309+
modules.Add( Module("circl") )
309310
modules.Add( Module("cloudflare-bn256") )
310311
modules.Add( Module("crypto-js") )
311312
modules.Add( Module("elliptic") )

modules/circl/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
all: module.a cryptofuzz.a
2+
3+
CXXFLAGS += -Wall -Wextra -std=c++17 -I ../../include -I ../../fuzzing-headers/include -DFUZZING_HEADERS_NO_IMPL
4+
5+
module.a: module.o
6+
rm -rf tmp/
7+
mkdir tmp/
8+
cd tmp/ && ar x ../cryptofuzz.a && ar rcs ../module.a *.o ../module.o
9+
ranlib module.a
10+
rm -rf tmp/
11+
generate_ids : generate_ids.cpp
12+
$(CXX) $(CXXFLAGS) generate_ids.cpp -o generate_ids
13+
ids.go : generate_ids
14+
./generate_ids
15+
cryptofuzz.a: cryptofuzz.go ids.go
16+
go build -o cryptofuzz.a -buildmode=c-archive cryptofuzz.go ids.go
17+
module.o: cryptofuzz.a module.cpp module.h
18+
$(CXX) $(CXXFLAGS) -fPIC -c module.cpp -o module.o
19+
clean:
20+
rm -rf *.o module.a cryptofuzz.a cryptofuzz.h generate_ids ids.go

modules/circl/cryptofuzz.go

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"strconv"
6+
"encoding/hex"
7+
"encoding/json"
8+
"math/big"
9+
"github.com/cloudflare/circl/ecc/p384"
10+
)
11+
12+
import "C"
13+
14+
type ByteSlice []byte
15+
type Type uint64
16+
17+
type SliceOpt struct {
18+
slice ByteSlice
19+
opt byte
20+
}
21+
22+
func (t *Type) UnmarshalJSON(in []byte) error {
23+
res, err := strconv.ParseUint(string(in[1:len(in)-1]), 10, 64)
24+
*t = Type(res)
25+
return err
26+
}
27+
28+
func (b *ByteSlice) MarshalJSON() ([]byte, error) {
29+
var buffer bytes.Buffer
30+
buffer.WriteString("\"")
31+
buffer.WriteString(hex.EncodeToString(*b))
32+
buffer.WriteString("\"")
33+
return buffer.Bytes(), nil
34+
}
35+
36+
func (b *ByteSlice) UnmarshalJSON(in []byte) error {
37+
res, err := hex.DecodeString(string(in[1:len(in)-1]))
38+
*b = res
39+
return err
40+
}
41+
42+
func decodeBignum(s string) *big.Int {
43+
if s == "" {
44+
s = "0"
45+
}
46+
47+
bn, ok := new(big.Int).SetString(s, 10)
48+
if ok == false {
49+
panic("Cannot decode bignum")
50+
}
51+
return bn
52+
}
53+
54+
type OpECC_Point_Add struct {
55+
Modifier ByteSlice
56+
CurveType Type
57+
A_x string
58+
A_y string
59+
B_x string
60+
B_y string
61+
}
62+
63+
type OpECC_Point_Mul struct {
64+
Modifier ByteSlice
65+
CurveType Type
66+
A_x string
67+
A_y string
68+
B string
69+
}
70+
71+
type OpECC_Point_Dbl struct {
72+
Modifier ByteSlice
73+
CurveType Type
74+
A_x string
75+
A_y string
76+
}
77+
78+
var result []byte
79+
80+
func resetResult() {
81+
result = []byte{}
82+
}
83+
84+
func setResult(r ByteSlice) {
85+
r2, err := json.Marshal(&r)
86+
if err != nil {
87+
panic("Cannot marshal to JSON")
88+
}
89+
result = r2
90+
}
91+
92+
func unmarshal(in []byte, op interface{}) {
93+
err := json.Unmarshal(in, &op)
94+
if err != nil {
95+
panic("Cannot unmarshal JSON, which is expected to be well-formed")
96+
}
97+
}
98+
99+
//export circl_Cryptofuzz_GetResult
100+
func circl_Cryptofuzz_GetResult() *C.char {
101+
return C.CString(string(result))
102+
}
103+
104+
//export circl_Cryptofuzz_OpECC_Point_Add
105+
func circl_Cryptofuzz_OpECC_Point_Add(in []byte) {
106+
resetResult()
107+
108+
var op OpECC_Point_Add
109+
unmarshal(in, &op)
110+
111+
if !issecp384r1(op.CurveType) {
112+
return
113+
}
114+
115+
curve := p384.P384()
116+
117+
a_x := decodeBignum(op.A_x)
118+
a_y := decodeBignum(op.A_y)
119+
120+
b_x := decodeBignum(op.B_x)
121+
b_y := decodeBignum(op.B_y)
122+
123+
res_x, res_y := curve.Add(a_x, a_y, b_x, b_y)
124+
125+
if curve.IsOnCurve(a_x, a_y) == false {
126+
return
127+
}
128+
129+
if curve.IsOnCurve(b_x, b_y) == false {
130+
return
131+
}
132+
133+
res := make([]string, 2)
134+
res[0], res[1] = res_x.String(), res_y.String()
135+
136+
r2, err := json.Marshal(&res)
137+
if err != nil {
138+
panic("Cannot marshal to JSON")
139+
}
140+
141+
result = r2
142+
}
143+
144+
//export circl_Cryptofuzz_OpECC_Point_Mul
145+
func circl_Cryptofuzz_OpECC_Point_Mul(in []byte) {
146+
resetResult()
147+
148+
var op OpECC_Point_Mul
149+
unmarshal(in, &op)
150+
151+
if !issecp384r1(op.CurveType) {
152+
return
153+
}
154+
155+
curve := p384.P384()
156+
157+
a_x := decodeBignum(op.A_x)
158+
a_y := decodeBignum(op.A_y)
159+
160+
b := decodeBignum(op.B)
161+
/* https://github.com/cloudflare/circl/issues/312 */
162+
order := decodeBignum("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643")
163+
if ( b.Cmp(order) >= 0 ) {
164+
return
165+
}
166+
167+
res_x, res_y := curve.ScalarMult(a_x, a_y, b.Bytes())
168+
169+
if curve.IsOnCurve(a_x, a_y) == false {
170+
return
171+
}
172+
173+
res := make([]string, 2)
174+
res[0], res[1] = res_x.String(), res_y.String()
175+
176+
r2, err := json.Marshal(&res)
177+
if err != nil {
178+
panic("Cannot marshal to JSON")
179+
}
180+
181+
result = r2
182+
}
183+
184+
//export circl_Cryptofuzz_OpECC_Point_Dbl
185+
func circl_Cryptofuzz_OpECC_Point_Dbl(in []byte) {
186+
resetResult()
187+
188+
var op OpECC_Point_Dbl
189+
unmarshal(in, &op)
190+
191+
if !issecp384r1(op.CurveType) {
192+
return
193+
}
194+
195+
curve := p384.P384()
196+
197+
a_x := decodeBignum(op.A_x)
198+
a_y := decodeBignum(op.A_y)
199+
200+
res_x, res_y := curve.Double(a_x, a_y)
201+
202+
if curve.IsOnCurve(a_x, a_y) == false {
203+
return
204+
}
205+
206+
res := make([]string, 2)
207+
res[0], res[1] = res_x.String(), res_y.String()
208+
209+
r2, err := json.Marshal(&res)
210+
if err != nil {
211+
panic("Cannot marshal to JSON")
212+
}
213+
214+
result = r2
215+
}
216+
217+
func main() { }

modules/circl/generate_ids.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <cstdint>
2+
#include <cstddef>
3+
#include <stdio.h>
4+
#include <regex>
5+
#include <fuzzing/datasource/id.hpp>
6+
#include "../../repository_map.h"
7+
8+
int main(void)
9+
{
10+
FILE* fp = fopen("ids.go", "wb");
11+
fprintf(fp, "package main\n");
12+
for (const auto& digest : DigestLUTMap ) {
13+
auto digestStr = std::string(digest.second.name);
14+
digestStr = std::regex_replace(digestStr, std::regex("[.-]"), "_");
15+
fprintf(fp, "func is%s(id Type) bool { return id == %s }\n", digestStr.c_str(), std::to_string(digest.first).c_str());
16+
}
17+
for (const auto& cipher : CipherLUTMap ) {
18+
auto cipherStr = std::string(cipher.second.name);
19+
cipherStr = std::regex_replace(cipherStr, std::regex("[.-]"), "_");
20+
if ( cipherStr == "GOST_28147_89" ) {
21+
/* XXX */
22+
continue;
23+
}
24+
fprintf(fp, "func is%s(id Type) bool { return id == %s }\n", cipherStr.c_str(), std::to_string(cipher.first).c_str());
25+
}
26+
for (const auto& curve : ECC_CurveLUTMap ) {
27+
auto curveStr = std::string(curve.second.name);
28+
curveStr = std::regex_replace(curveStr, std::regex("[.-]"), "_");
29+
fprintf(fp, "func is%s(id Type) bool { return id == %s }\n", curveStr.c_str(), std::to_string(curve.first).c_str());
30+
}
31+
for (const auto& bnOp : CalcOpLUTMap ) {
32+
auto bnOpStr = std::string(bnOp.second.name);
33+
bnOpStr = std::regex_replace(bnOpStr, std::regex("\\(.*"), "");
34+
fprintf(fp, "func is%s(id Type) bool { return id == %s }\n", bnOpStr.c_str(), std::to_string(bnOp.first).c_str());
35+
}
36+
fclose(fp);
37+
}

modules/circl/module.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include "module.h"
2+
#include <cryptofuzz/util.h>
3+
#include <cryptofuzz/repository.h>
4+
#include <fuzzing/datasource/id.hpp>
5+
#include <boost/lexical_cast.hpp>
6+
7+
extern "C" {
8+
#include "cryptofuzz.h"
9+
}
10+
11+
namespace cryptofuzz {
12+
namespace module {
13+
14+
circl::circl(void) :
15+
Module("circl") {
16+
}
17+
18+
std::string circl::getResult(void) const {
19+
auto res = circl_Cryptofuzz_GetResult();
20+
std::string ret(res);
21+
free(res);
22+
return ret;
23+
}
24+
25+
std::optional<nlohmann::json> circl::getJsonResult(void) const {
26+
const auto res = getResult();
27+
if ( res.empty() ) {
28+
return std::nullopt;
29+
}
30+
31+
try {
32+
return nlohmann::json::parse(getResult());
33+
} catch ( std::exception e ) {
34+
/* Must always parse correctly non-empty strings */
35+
abort();
36+
}
37+
}
38+
39+
template <class T> std::optional<T> circl::getResultAs(void) const {
40+
std::optional<T> ret = std::nullopt;
41+
42+
auto j = getJsonResult();
43+
if ( j != std::nullopt ) {
44+
ret = T(*j);
45+
}
46+
47+
return ret;
48+
}
49+
50+
static GoSlice toGoSlice(std::string& in) {
51+
return {in.data(), static_cast<GoInt>(in.size()), static_cast<GoInt>(in.size())};
52+
}
53+
54+
std::optional<component::ECC_Point> circl::OpECC_Point_Add(operation::ECC_Point_Add& op) {
55+
auto jsonStr = op.ToJSON().dump();
56+
circl_Cryptofuzz_OpECC_Point_Add(toGoSlice(jsonStr));
57+
58+
return getResultAs<component::ECC_Point>();
59+
}
60+
61+
std::optional<component::ECC_Point> circl::OpECC_Point_Mul(operation::ECC_Point_Mul& op) {
62+
auto jsonStr = op.ToJSON().dump();
63+
circl_Cryptofuzz_OpECC_Point_Mul(toGoSlice(jsonStr));
64+
65+
return getResultAs<component::ECC_Point>();
66+
}
67+
68+
std::optional<component::ECC_Point> circl::OpECC_Point_Dbl(operation::ECC_Point_Dbl& op) {
69+
auto jsonStr = op.ToJSON().dump();
70+
circl_Cryptofuzz_OpECC_Point_Dbl(toGoSlice(jsonStr));
71+
72+
return getResultAs<component::ECC_Point>();
73+
}
74+
75+
} /* namespace module */
76+
} /* namespace cryptofuzz */

0 commit comments

Comments
 (0)