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

[ms-go1.23-support] Support MD5SHA1 in PKCS1 v1.5 signatures #227

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
29 changes: 18 additions & 11 deletions evp.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ func hashToMD(h hash.Hash) C.GO_EVP_MD_PTR {
return nil
}

func evp_md5_sha1() C.GO_EVP_MD_PTR {
if vMajor == 1 && vMinor == 0 {
return C.go_openssl_EVP_md5_sha1_backport()
} else {
return C.go_openssl_EVP_md5_sha1()
}
}

// cryptoHashToMD converts a crypto.Hash to a GO_EVP_MD_PTR.
func cryptoHashToMD(ch crypto.Hash) (md C.GO_EVP_MD_PTR) {
if v, ok := cacheMD.Load(ch); ok {
Expand Down Expand Up @@ -76,17 +84,9 @@ func cryptoHashToMD(ch crypto.Hash) (md C.GO_EVP_MD_PTR) {
}
cacheMD.Store(ch, md)
}()
// SupportsHash returns false for MD5SHA1 because we don't
// provide a hash.Hash implementation for it. Yet, it can
// still be used when signing/verifying with an RSA key.
if ch == crypto.MD5SHA1 {
if vMajor == 1 && vMinor == 0 {
return C.go_openssl_EVP_md5_sha1_backport()
} else {
return C.go_openssl_EVP_md5_sha1()
}
}
switch ch {
case crypto.MD5SHA1:
return evp_md5_sha1()
case crypto.MD4:
return C.go_openssl_EVP_md4()
case crypto.MD5:
Expand Down Expand Up @@ -265,7 +265,14 @@ func setupEVP(withKey withKeyFunc, padding C.int,
// We support unhashed messages.
md := cryptoHashToMD(ch)
if md == nil {
return nil, errors.New("crypto/rsa: unsupported hash function")
if ch == crypto.MD5SHA1 {
// Most providers will special-case MD5SHA1 to support it in RSA PKCS1 signatures,
// as it is used in TLS 1.0 and 1.1. Try to use it even if EVP_MD_fetch says it is not supported.
// Worst case, user will see the EVP_PKEY_CTX_ctrl error message instead of the one just below.
md = evp_md5_sha1()
} else {
return nil, errors.New("crypto/rsa: unsupported hash function")
}
}
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1, -1, C.GO_EVP_PKEY_CTRL_MD, 0, unsafe.Pointer(md)) != 1 {
return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed")
Expand Down
22 changes: 22 additions & 0 deletions rsa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,28 @@ func TestSignVerifyPKCS1v15(t *testing.T) {
}
}

func TestSignVerifyPKCS1v15_MD5SHA1(t *testing.T) {
priv, pub := newRSAKey(t, 2048)

// Construct a fake MD5+SHA1 hash.
hashed := make([]byte, crypto.MD5.Size()+crypto.SHA1.Size())
hashed[0] = 0x30

signed, err := openssl.SignRSAPKCS1v15(priv, crypto.MD5SHA1, hashed)
if err != nil {
if openssl.FIPS() {
// This test is not supported in FIPS mode, but at least we
// can check that we don't panic (which we have before when using SCOSSL).
t.Skip("skipping test in FIPS mode")
}
t.Fatal(err)
}
err = openssl.VerifyRSAPKCS1v15(pub, crypto.MD5SHA1, hashed, signed)
if err != nil {
t.Fatal(err)
}
}

func TestSignVerifyPKCS1v15_Unhashed(t *testing.T) {
msg := []byte("hi!")
priv, pub := newRSAKey(t, 2048)
Expand Down
Loading