Skip to content

Commit 098cd1c

Browse files
Merge pull request #78 from godaddy/add-disable-zero-copy
Add DisableZeroCopy config option
2 parents 57901c8 + 3062179 commit 098cd1c

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

internal/asherah/options.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type Options struct {
2424
PreferredRegion string `long:"preferred-region" description:"The preferred AWS region (required if --kms=aws)" env:"ASHERAH_PREFERRED_REGION"`
2525
EnableRegionSuffix bool `long:"enable-region-suffix" description:"Configure the metastore to use regional suffixes (only supported by --metastore=dynamodb)" env:"ASHERAH_ENABLE_REGION_SUFFIX"`
2626
EnableSessionCaching bool `long:"enable-session-caching" description:"Enable shared session caching" env:"ASHERAH_ENABLE_SESSION_CACHING"`
27+
DisableZeroCopy bool `long:"disable-zero-copy" description:"Disable zero-copy FFI input buffers to prevent use-after-free from caller runtime" env:"ASHERAH_DISABLE_ZERO_COPY"`
2728
Verbose bool `short:"v" long:"verbose" description:"Enable verbose logging output" env:"ASHERAH_VERBOSE"`
2829
}
2930

libasherah.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
)
2020

2121
var EstimatedIntermediateKeyOverhead = 0
22+
var DisableZeroCopy = false
2223

2324
func main() {
2425
}
@@ -92,6 +93,7 @@ func SetupJson(configJson unsafe.Pointer) int32 {
9293
log.DebugLog("Successfully deserialized config JSON")
9394

9495
EstimatedIntermediateKeyOverhead = len(options.ProductID) + len(options.ServiceName)
96+
DisableZeroCopy = options.DisableZeroCopy
9597

9698
err := asherah.Setup(options)
9799
if err == asherah.ErrAsherahAlreadyInitialized {
@@ -304,6 +306,12 @@ func encryptData(partitionIdPtr unsafe.Pointer, dataPtr unsafe.Pointer) (*appenc
304306
return nil, result, errors.New(errorMessage)
305307
}
306308

309+
if DisableZeroCopy {
310+
dataCopy := make([]byte, len(data))
311+
copy(dataCopy, data)
312+
data = dataCopy
313+
}
314+
307315
drr, err := asherah.Encrypt(partitionId, data)
308316
if err != nil {
309317
if err == asherah.ErrAsherahNotInitialized {

libasherah_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,90 @@ func TestEncryptDecryptRoundTrip(t *testing.T) {
282282
}
283283
}
284284

285+
func TestEncryptDecryptRoundTripWithDefensiveCopy(t *testing.T) {
286+
config := &asherah.Options{}
287+
288+
config.KMS = "static"
289+
config.ServiceName = "TestService"
290+
config.ProductID = "TestProduct"
291+
config.Metastore = "memory"
292+
config.EnableSessionCaching = true
293+
config.SessionCacheDuration = 1000
294+
config.SessionCacheMaxSize = 2
295+
config.ExpireAfter = 1000
296+
config.CheckInterval = 1000
297+
config.Verbose = Verbose
298+
config.DisableZeroCopy = true
299+
config.RegionMap = asherah.RegionMap{}
300+
config.RegionMap["region1"] = "arn1"
301+
config.RegionMap["region2"] = "arn2"
302+
303+
buf := testAllocateJsonBuffer(t, config)
304+
305+
result := SetupJson(cobhan.Ptr(&buf))
306+
if result != cobhan.ERR_NONE {
307+
t.Errorf("SetupJson returned %v", result)
308+
}
309+
defer Shutdown()
310+
311+
if !DisableZeroCopy {
312+
t.Error("DisableZeroCopy was not set by SetupJson")
313+
}
314+
315+
input := "InputData"
316+
partitionId := testAllocateStringBuffer(t, "Partition")
317+
data := testAllocateStringBuffer(t, input)
318+
encryptedData := cobhan.AllocateBuffer(256)
319+
encryptedKey := cobhan.AllocateBuffer(256)
320+
createdBuf := cobhan.AllocateBuffer(8)
321+
parentKeyId := cobhan.AllocateBuffer(256)
322+
parentKeyCreatedBuf := cobhan.AllocateBuffer(8)
323+
324+
result = Encrypt(cobhan.Ptr(&partitionId),
325+
cobhan.Ptr(&data),
326+
cobhan.Ptr(&encryptedData),
327+
cobhan.Ptr(&encryptedKey),
328+
cobhan.Ptr(&createdBuf),
329+
cobhan.Ptr(&parentKeyId),
330+
cobhan.Ptr(&parentKeyCreatedBuf),
331+
)
332+
if result != cobhan.ERR_NONE {
333+
t.Errorf("Encrypt returned %v", result)
334+
}
335+
336+
decryptedData := cobhan.AllocateBuffer(256)
337+
338+
created, result := cobhan.BufferToInt64Safe(&createdBuf)
339+
if result != cobhan.ERR_NONE {
340+
t.Errorf("BufferToInt64Safe returned %v", result)
341+
}
342+
343+
parentKeyCreated, result := cobhan.BufferToInt64Safe(&parentKeyCreatedBuf)
344+
if result != cobhan.ERR_NONE {
345+
t.Errorf("BufferToInt64Safe returned %v", result)
346+
}
347+
348+
result = Decrypt(cobhan.Ptr(&partitionId),
349+
cobhan.Ptr(&encryptedData),
350+
cobhan.Ptr(&encryptedKey),
351+
created,
352+
cobhan.Ptr(&parentKeyId),
353+
parentKeyCreated,
354+
cobhan.Ptr(&decryptedData),
355+
)
356+
if result != cobhan.ERR_NONE {
357+
t.Errorf("Decrypt returned %v", result)
358+
}
359+
360+
output, result := cobhan.BufferToStringSafe(&decryptedData)
361+
if result != cobhan.ERR_NONE {
362+
t.Errorf("BufferToStringSafe returned %v", result)
363+
}
364+
if output != input {
365+
t.Errorf("Expected %v Actual %v", input, output)
366+
}
367+
}
368+
285369
func TestEncryptWithoutInit(t *testing.T) {
286370
partitionId := testAllocateStringBuffer(t, "Partition")
287371
data := testAllocateStringBuffer(t, "InputData")

0 commit comments

Comments
 (0)