Skip to content
Merged
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
Prev Previous commit
reduce diffs
  • Loading branch information
qmuntal committed May 26, 2025
commit 00f166734d899230c6f1f901a172c1263c34adcc
37 changes: 32 additions & 5 deletions evp.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,14 @@ const (
)

type hashAlgorithm struct {
md C.GO_EVP_MD_PTR
ch crypto.Hash
size int
blockSize int
provider provider
md C.GO_EVP_MD_PTR
ch crypto.Hash
size int
blockSize int
provider provider
marshallable bool
magic string
marshalledSize int
}

// loadHash converts a crypto.Hash to a EVP_MD.
Expand All @@ -100,6 +103,8 @@ func loadHash(ch crypto.Hash) *hashAlgorithm {
hash.md = C.go_openssl_EVP_md4()
case crypto.MD5:
hash.md = C.go_openssl_EVP_md5()
hash.magic = magicMD5
hash.marshalledSize = marshaledSizeMD5
case crypto.MD5SHA1:
if vMajor == 1 && vMinor == 0 {
// OpenSSL 1.0.2 does not support MD5SHA1.
Expand All @@ -109,21 +114,35 @@ func loadHash(ch crypto.Hash) *hashAlgorithm {
}
case crypto.SHA1:
hash.md = C.go_openssl_EVP_sha1()
hash.magic = magic1
hash.marshalledSize = marshaledSize1
case crypto.SHA224:
hash.md = C.go_openssl_EVP_sha224()
hash.magic = magic224
hash.marshalledSize = marshaledSize256
case crypto.SHA256:
hash.md = C.go_openssl_EVP_sha256()
hash.magic = magic256
hash.marshalledSize = marshaledSize256
case crypto.SHA384:
hash.md = C.go_openssl_EVP_sha384()
hash.magic = magic384
hash.marshalledSize = marshaledSize512
case crypto.SHA512:
hash.md = C.go_openssl_EVP_sha512()
hash.magic = magic512
hash.marshalledSize = marshaledSize512
case crypto.SHA512_224:
if versionAtOrAbove(1, 1, 1) {
hash.md = C.go_openssl_EVP_sha512_224()
hash.magic = magic512_224
hash.marshalledSize = marshaledSize512
}
case crypto.SHA512_256:
if versionAtOrAbove(1, 1, 1) {
hash.md = C.go_openssl_EVP_sha512_256()
hash.magic = magic512_256
hash.marshalledSize = marshaledSize512
}
case crypto.SHA3_224:
if versionAtOrAbove(1, 1, 1) {
Expand Down Expand Up @@ -161,6 +180,11 @@ func loadHash(ch crypto.Hash) *hashAlgorithm {
hash.md = md
}
}
if hash.magic != "" {
if hash.marshalledSize == 0 {
panic("marshalledSize must be set for " + hash.magic)
}
}

switch vMajor {
case 1:
Expand All @@ -170,10 +194,13 @@ func loadHash(ch crypto.Hash) *hashAlgorithm {
switch C.GoString(C.go_openssl_OSSL_PROVIDER_get0_name(prov)) {
case "default":
hash.provider = providerOSSLDefault
hash.marshallable = hash.magic != ""
case "fips":
hash.provider = providerOSSLFIPS
hash.marshallable = hash.magic != ""
case "symcryptprovider":
hash.provider = providerSymCrypt
hash.marshallable = hash.magic != "" && isSymCryptHashStateSerializable(hash.md)
}
}
default:
Expand Down
58 changes: 18 additions & 40 deletions hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ const (
magic512_256 = "sha\x06"
magic512 = "sha\x07"

marshaledSizeMD5 = len(magicMD5) + 4*4 + 64 + 8
marshaledSize1 = len(magic1) + 5*4 + 64 + 8
marshaledSize256 = len(magic256) + 8*4 + 64 + 8
marshaledSize512 = len(magic512) + 8*8 + 128 + 8
marshaledSizeMD5 = len(magicMD5) + 4*4 + 64 + 8 // from crypto/md5
marshaledSize1 = len(magic1) + 5*4 + 64 + 8 // from crypto/sha1
marshaledSize256 = len(magic256) + 8*4 + 64 + 8 // from crypto/sha256
marshaledSize512 = len(magic512) + 8*8 + 128 + 8 // from crypto/sha512
)

// maxHashSize is the size of SHA52 and SHA3_512, the largest hashes we support.
Expand Down Expand Up @@ -382,70 +382,48 @@ func (h *evpHash) Clone() hash.Hash {
var errHashNotMarshallable = errors.New("openssl: hash state is not marshallable")

func (d *evpHash) MarshalBinary() ([]byte, error) {
buf := make([]byte, 0, marshaledSize512) // stack allocate the buffer by setting the max size we support
if !d.alg.marshallable {
return nil, errHashNotMarshallable
}
buf := make([]byte, 0, d.alg.marshalledSize)
return d.AppendBinary(buf)
}

func (d *evpHash) AppendBinary(buf []byte) ([]byte, error) {
defer runtime.KeepAlive(d)
d.init()
magic, _ := cryptoHashEncodingInfo(d.alg.ch)
if magic == "" {
if !d.alg.marshallable {
return nil, errHashNotMarshallable
}
switch d.alg.provider {
case providerOSSLDefault, providerOSSLFIPS:
return osslHashAppendBinary(d.ctx, d.alg.ch, magic, buf)
return osslHashAppendBinary(d.ctx, d.alg.ch, d.alg.magic, buf)
case providerSymCrypt:
return symCryptHashAppendBinary(d.ctx, d.alg.ch, magic, buf)
return symCryptHashAppendBinary(d.ctx, d.alg.ch, d.alg.magic, buf)
default:
return nil, errHashNotMarshallable
panic("openssl: unknown hash provider" + strconv.Itoa(int(d.alg.provider)))
}
}

func (d *evpHash) UnmarshalBinary(b []byte) error {
defer runtime.KeepAlive(d)
d.init()
magic, size := cryptoHashEncodingInfo(d.alg.ch)
if magic == "" {
if !d.alg.marshallable {
return errHashNotMarshallable
}
if len(b) < len(magic) || string(b[:len(magic)]) != string(magic[:]) {
if len(b) < len(d.alg.magic) || string(b[:len(d.alg.magic)]) != d.alg.magic {
return errors.New("openssl: invalid hash state identifier")
}
if len(b) != size {
if len(b) != d.alg.marshalledSize {
return errors.New("openssl: invalid hash state size")
}
switch d.alg.provider {
case providerOSSLDefault, providerOSSLFIPS:
return osslHashUnmarshalBinary(d.ctx, d.alg.ch, magic, b)
return osslHashUnmarshalBinary(d.ctx, d.alg.ch, d.alg.magic, b)
case providerSymCrypt:
return symCryptHashUnmarshalBinary(d.ctx, d.alg.ch, magic, b)
default:
return errHashNotMarshallable
}
}

func cryptoHashEncodingInfo(ch crypto.Hash) (magic string, size int) {
switch ch {
case crypto.MD5:
return magicMD5, marshaledSizeMD5
case crypto.SHA1:
return magic1, marshaledSize1
case crypto.SHA224:
return magic224, marshaledSize256
case crypto.SHA256:
return magic256, marshaledSize256
case crypto.SHA384:
return magic384, marshaledSize512
case crypto.SHA512_224:
return magic512_224, marshaledSize512
case crypto.SHA512_256:
return magic512_256, marshaledSize512
case crypto.SHA512:
return magic512, marshaledSize512
return symCryptHashUnmarshalBinary(d.ctx, d.alg.ch, d.alg.magic, b)
default:
return "", 0
panic("openssl: unknown hash provider" + strconv.Itoa(int(d.alg.provider)))
}
}

Expand Down
26 changes: 16 additions & 10 deletions params.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package openssl
// #include "goopenssl.h"
import "C"
import (
"math"
"runtime"
"unsafe"
)
Expand Down Expand Up @@ -47,34 +46,45 @@ var (
_OSSL_MAC_PARAM_DIGEST = C.CString("digest")
)

const _OSSL_PARAM_UNMODIFIED uint = uint(^uintptr(0))

// _OSSL_PARAM is a structure to pass or request object parameters.
// https://docs.openssl.org/3.0/man3/OSSL_PARAM/.
type _OSSL_PARAM struct {
Key *C.char
DataType uint32
Data unsafe.Pointer
DataSize int
ReturnSize int
DataSize uint
ReturnSize uint
}

func ossl_param_construct(key *C.char, dataType uint32, data unsafe.Pointer, dataSize int) _OSSL_PARAM {
return _OSSL_PARAM{
Key: key,
DataType: dataType,
Data: data,
DataSize: dataSize,
ReturnSize: math.MaxInt - 1,
DataSize: uint(dataSize),
ReturnSize: _OSSL_PARAM_UNMODIFIED,
}
}

func _OSSL_PARAM_construct_octet_string(key *C.char, data unsafe.Pointer, dataSize int) _OSSL_PARAM {
return ossl_param_construct(key, C.GO_OSSL_PARAM_OCTET_STRING, data, dataSize)
}

func _OSSL_PARAM_construct_int32(key *C.char, data *int32) _OSSL_PARAM {
return ossl_param_construct(key, C.GO_OSSL_PARAM_INTEGER, unsafe.Pointer(data), 4)
}

func _OSSL_PARAM_construct_end() _OSSL_PARAM {
return _OSSL_PARAM{}
}

func _OSSL_PARAM_modified(param *_OSSL_PARAM) bool {
// If ReturnSize is not set, the parameter has not been modified.
return param != nil && param.ReturnSize != _OSSL_PARAM_UNMODIFIED
}

type bnParam struct {
value C.GO_BIGNUM_PTR
private bool
Expand All @@ -94,17 +104,13 @@ type paramBuilder struct {

// newParamBuilder creates a new paramBuilder.
func newParamBuilder() (*paramBuilder, error) {
return newParamBuilderN(8) // the maximum known number of BIGNUMs to free are 8 for RSA
}

func newParamBuilderN(n int) (*paramBuilder, error) {
bld := C.go_openssl_OSSL_PARAM_BLD_new()
if bld == nil {
return nil, newOpenSSLError("OSSL_PARAM_BLD_new")
}
pb := &paramBuilder{
bld: bld,
bnToFree: make([]bnParam, 0, n),
bnToFree: make([]bnParam, 0, 8), // the maximum known number of BIGNUMs to free are 8 for RSA
}
runtime.SetFinalizer(pb, (*paramBuilder).finalize)
return pb, nil
Expand Down
Loading
Loading