Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wrapper for EVP_BPE_scrypt #246

Open
wants to merge 2 commits into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions scrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//go:build !cmd_go_bootstrap

package openssl

// #include "goopenssl.h"
import "C"
import (
"unsafe"
)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EVP_PBE_scrypt is supported since OpenSSL 3, and maybe not for all providers. Please implement the SupportsSscrypt() bool function. The implementation will be almost identical to

func SupportsPBKDF2() bool {
, replacing PBKDF2 with SCRYPT and returning false in the OpenSSL 1 case.

Then use this function in the new test cases.

func Scrypt(password string, salt []byte, N, r, p, maxmem, keylen uint64) ([]byte, error) {
harrybrwn marked this conversation as resolved.
Show resolved Hide resolved
cpassword := C.CString(password)
defer C.free((unsafe.Pointer)(cpassword))

csalt := C.CBytes(salt)
defer C.free((unsafe.Pointer)(csalt))

key := C.malloc(C.size_t(keylen))
defer C.free(key)
harrybrwn marked this conversation as resolved.
Show resolved Hide resolved

res := C.go_openssl_EVP_PBE_scrypt(
cpassword,
harrybrwn marked this conversation as resolved.
Show resolved Hide resolved
C.size_t(len(password)),
(*C.uchar)(csalt),
harrybrwn marked this conversation as resolved.
Show resolved Hide resolved
C.size_t(len(salt)),
C.uint64_t(N),
C.uint64_t(r),
C.uint64_t(p),
C.uint64_t(maxmem),
(*C.uchar)(key),
C.size_t(keylen),
)
if res != 1 {
return nil, newOpenSSLError("EVP_PBE_scrypt")
}
return C.GoBytes(key, C.int(keylen)), nil
}
36 changes: 36 additions & 0 deletions scrypt_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build !cmd_go_bootstrap

package openssl_test

import (
"fmt"
"testing"

"github.com/golang-fips/openssl/v2"
)

func TestScrypt(t *testing.T) {
hash, err := openssl.Scrypt("testpass01", []byte("abc123"), 1<<14, 8, 1, 32<<20, 64)
if err != nil {
t.Fatal(err)
}
if len(hash) == 0 {
t.Error("zero length hash")
}
hexhash := fmt.Sprintf("%x", hash)
exp := "e6a3569950bf90e88d2f114c3d43f2d103cf3c13cf1579095e88ff5b3b3eb379cad31d26aa533e0f32c10666bbcc9c1cac2775a8a60d55d55d63c401927e905e"
if hexhash != exp {
t.Errorf("expected %q, got %q", exp, hexhash)
}
}

func TestScrypt_Err(t *testing.T) {
_, err := openssl.Scrypt("testpass01", []byte("abc123"), 1<<14, 0, 0, 32<<20, 64)
if err == nil {
t.Error("expected an error when using zeros for r and p")
}
_, err = openssl.Scrypt("x", []byte("y"), 1<<14, 8, 1, 1<<20, 32)
if err == nil {
t.Error("expected memory limit error")
}
}
2 changes: 1 addition & 1 deletion shims.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,4 +410,4 @@ DEFINEFUNC_3_0(int, EVP_KDF_CTX_set_params, (GO_EVP_KDF_CTX_PTR ctx, const GO_OS
DEFINEFUNC_3_0(void, EVP_KDF_CTX_free, (GO_EVP_KDF_CTX_PTR ctx), (ctx)) \
DEFINEFUNC_3_0(size_t, EVP_KDF_CTX_get_kdf_size, (GO_EVP_KDF_CTX_PTR ctx), (ctx)) \
DEFINEFUNC_3_0(int, EVP_KDF_derive, (GO_EVP_KDF_CTX_PTR ctx, unsigned char *key, size_t keylen, const GO_OSSL_PARAM_PTR params), (ctx, key, keylen, params)) \

DEFINEFUNC_1_1_1(int, EVP_PBE_scrypt, (const char *pass, size_t passlen, const unsigned char *salt, size_t saltlen, uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, unsigned char *key, size_t keylen), (pass, passlen, salt, saltlen, N, r, p, maxmem, key, keylen))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EVP_PBE_scrypt is defined since OpenSSL 3.0

Suggested change
DEFINEFUNC_1_1_1(int, EVP_PBE_scrypt, (const char *pass, size_t passlen, const unsigned char *salt, size_t saltlen, uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, unsigned char *key, size_t keylen), (pass, passlen, salt, saltlen, N, r, p, maxmem, key, keylen))
DEFINEFUNC_3_0(int, EVP_PBE_scrypt, (const char *pass, size_t passlen, const unsigned char *salt, size_t saltlen, uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, unsigned char *key, size_t keylen), (pass, passlen, salt, saltlen, N, r, p, maxmem, key, keylen)) \

Loading