Skip to content

Commit

Permalink
support MD5HA1 in PKCS1 v1.5 signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
qmuntal committed Nov 26, 2024
1 parent c5672cc commit ec8b7ed
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 11 deletions.
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)

// Manually hash the message with MD5-SHA1.
md5, sha1 := openssl.NewMD5(), openssl.NewSHA1()
md5sha1 := make([]byte, md5.Size()+sha1.Size())
msg := []byte("hi!")
md5.Write(msg)
sha1.Write(msg)
copy(md5sha1, md5.Sum(nil))
copy(md5sha1[md5.Size():], sha1.Sum(nil))

signed, err := openssl.SignRSAPKCS1v15(priv, crypto.MD5SHA1, md5sha1)
if err != nil {
t.Fatal(err)
}
err = openssl.VerifyRSAPKCS1v15(pub, crypto.MD5SHA1, md5sha1, signed)
if err != nil {
t.Fatal(err)
}
}

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

0 comments on commit ec8b7ed

Please sign in to comment.