@@ -48,29 +48,8 @@ func hashFuncHash(fn func() hash.Hash) (h hash.Hash, err error) {
48
48
49
49
// hashToMD converts a hash.Hash implementation from this package to a GO_EVP_MD_PTR.
50
50
func hashToMD (h hash.Hash ) C.GO_EVP_MD_PTR {
51
- var ch crypto.Hash
52
- switch h .(type ) {
53
- case * sha1Hash , * sha1Marshal :
54
- ch = crypto .SHA1
55
- case * sha224Hash , * sha224Marshal :
56
- ch = crypto .SHA224
57
- case * sha256Hash , * sha256Marshal :
58
- ch = crypto .SHA256
59
- case * sha384Hash , * sha384Marshal :
60
- ch = crypto .SHA384
61
- case * sha512Hash , * sha512Marshal :
62
- ch = crypto .SHA512
63
- case * sha3_224Hash :
64
- ch = crypto .SHA3_224
65
- case * sha3_256Hash :
66
- ch = crypto .SHA3_256
67
- case * sha3_384Hash :
68
- ch = crypto .SHA3_384
69
- case * sha3_512Hash :
70
- ch = crypto .SHA3_512
71
- }
72
- if ch != 0 {
73
- return cryptoHashToMD (ch )
51
+ if h , ok := h .(* evpHash ); ok {
52
+ return h .alg .md
74
53
}
75
54
return nil
76
55
}
@@ -89,78 +68,109 @@ func hashFuncToMD(fn func() hash.Hash) (C.GO_EVP_MD_PTR, error) {
89
68
return md , nil
90
69
}
91
70
92
- // cryptoHashToMD converts a crypto.Hash to a EVP_MD.
93
- func cryptoHashToMD (ch crypto.Hash ) C.GO_EVP_MD_PTR {
71
+ type hashAlgorithm struct {
72
+ md C.GO_EVP_MD_PTR
73
+ ch crypto.Hash
74
+ size int
75
+ blockSize int
76
+ marshallable bool
77
+ magic string
78
+ marshalledSize int
79
+ }
80
+
81
+ // loadHash converts a crypto.Hash to a EVP_MD.
82
+ func loadHash (ch crypto.Hash ) * hashAlgorithm {
94
83
if v , ok := cacheMD .Load (ch ); ok {
95
- return v .(C. GO_EVP_MD_PTR )
84
+ return v .(* hashAlgorithm )
96
85
}
97
- var md C.GO_EVP_MD_PTR
86
+
87
+ var hash hashAlgorithm
98
88
switch ch {
99
89
case crypto .RIPEMD160 :
100
- md = C .go_openssl_EVP_ripemd160 ()
90
+ hash . md = C .go_openssl_EVP_ripemd160 ()
101
91
case crypto .MD4 :
102
- md = C .go_openssl_EVP_md4 ()
92
+ hash . md = C .go_openssl_EVP_md4 ()
103
93
case crypto .MD5 :
104
- md = C .go_openssl_EVP_md5 ()
94
+ hash .md = C .go_openssl_EVP_md5 ()
95
+ hash .magic = md5Magic
96
+ hash .marshalledSize = md5MarshaledSize
105
97
case crypto .MD5SHA1 :
106
98
if vMajor == 1 && vMinor == 0 {
107
- md = C .go_openssl_EVP_md5_sha1_backport ()
99
+ hash . md = C .go_openssl_EVP_md5_sha1_backport ()
108
100
} else {
109
- md = C .go_openssl_EVP_md5_sha1 ()
101
+ hash . md = C .go_openssl_EVP_md5_sha1 ()
110
102
}
111
103
case crypto .SHA1 :
112
- md = C .go_openssl_EVP_sha1 ()
104
+ hash .md = C .go_openssl_EVP_sha1 ()
105
+ hash .magic = sha1Magic
106
+ hash .marshalledSize = sha1MarshaledSize
113
107
case crypto .SHA224 :
114
- md = C .go_openssl_EVP_sha224 ()
108
+ hash .md = C .go_openssl_EVP_sha224 ()
109
+ hash .magic = magic224
110
+ hash .marshalledSize = marshaledSize256
115
111
case crypto .SHA256 :
116
- md = C .go_openssl_EVP_sha256 ()
112
+ hash .md = C .go_openssl_EVP_sha256 ()
113
+ hash .magic = magic256
114
+ hash .marshalledSize = marshaledSize256
117
115
case crypto .SHA384 :
118
- md = C .go_openssl_EVP_sha384 ()
116
+ hash .md = C .go_openssl_EVP_sha384 ()
117
+ hash .magic = magic384
118
+ hash .marshalledSize = marshaledSize512
119
119
case crypto .SHA512 :
120
- md = C .go_openssl_EVP_sha512 ()
120
+ hash .md = C .go_openssl_EVP_sha512 ()
121
+ hash .magic = magic512
122
+ hash .marshalledSize = marshaledSize512
121
123
case crypto .SHA512_224 :
122
124
if versionAtOrAbove (1 , 1 , 1 ) {
123
- md = C .go_openssl_EVP_sha512_224 ()
125
+ hash .md = C .go_openssl_EVP_sha512_224 ()
126
+ hash .magic = magic512_224
127
+ hash .marshalledSize = marshaledSize512
124
128
}
125
129
case crypto .SHA512_256 :
126
130
if versionAtOrAbove (1 , 1 , 1 ) {
127
- md = C .go_openssl_EVP_sha512_256 ()
131
+ hash .md = C .go_openssl_EVP_sha512_256 ()
132
+ hash .magic = magic512_256
133
+ hash .marshalledSize = marshaledSize512
128
134
}
129
135
case crypto .SHA3_224 :
130
136
if versionAtOrAbove (1 , 1 , 1 ) {
131
- md = C .go_openssl_EVP_sha3_224 ()
137
+ hash . md = C .go_openssl_EVP_sha3_224 ()
132
138
}
133
139
case crypto .SHA3_256 :
134
140
if versionAtOrAbove (1 , 1 , 1 ) {
135
- md = C .go_openssl_EVP_sha3_256 ()
141
+ hash . md = C .go_openssl_EVP_sha3_256 ()
136
142
}
137
143
case crypto .SHA3_384 :
138
144
if versionAtOrAbove (1 , 1 , 1 ) {
139
- md = C .go_openssl_EVP_sha3_384 ()
145
+ hash . md = C .go_openssl_EVP_sha3_384 ()
140
146
}
141
147
case crypto .SHA3_512 :
142
148
if versionAtOrAbove (1 , 1 , 1 ) {
143
- md = C .go_openssl_EVP_sha3_512 ()
149
+ hash . md = C .go_openssl_EVP_sha3_512 ()
144
150
}
145
151
}
146
- if md == nil {
147
- cacheMD .Store (ch , nil )
152
+ if hash . md == nil {
153
+ cacheMD .Store (ch , ( * hashAlgorithm )( nil ) )
148
154
return nil
149
155
}
156
+ hash .ch = ch
157
+ hash .size = int (C .go_openssl_EVP_MD_get_size (hash .md ))
158
+ hash .blockSize = int (C .go_openssl_EVP_MD_get_block_size (hash .md ))
150
159
if vMajor == 3 {
151
160
// On OpenSSL 3, directly operating on a EVP_MD object
152
161
// not created by EVP_MD_fetch has negative performance
153
162
// implications, as digest operations will have
154
163
// to fetch it on every call. Better to just fetch it once here.
155
- md1 := C .go_openssl_EVP_MD_fetch (nil , C .go_openssl_EVP_MD_get0_name (md ), nil )
164
+ md := C .go_openssl_EVP_MD_fetch (nil , C .go_openssl_EVP_MD_get0_name (hash . md ), nil )
156
165
// Don't overwrite md in case it can't be fetched, as the md may still be used
157
166
// outside of EVP_MD_CTX, for example to sign and verify RSA signatures.
158
- if md1 != nil {
159
- md = md1
167
+ if md != nil {
168
+ hash . md = md
160
169
}
161
170
}
162
- cacheMD .Store (ch , md )
163
- return md
171
+ hash .marshallable = hash .magic != "" && isHashMarshallable (hash .md )
172
+ cacheMD .Store (ch , & hash )
173
+ return & hash
164
174
}
165
175
166
176
// generateEVPPKey generates a new EVP_PKEY with the given id and properties.
@@ -302,11 +312,11 @@ func setupEVP(withKey withKeyFunc, padding C.int,
302
312
}
303
313
}
304
314
case C .GO_RSA_PKCS1_PSS_PADDING :
305
- md := cryptoHashToMD (ch )
306
- if md == nil {
315
+ alg := loadHash (ch )
316
+ if alg == nil {
307
317
return nil , errors .New ("crypto/rsa: unsupported hash function" )
308
318
}
309
- if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , C .GO_EVP_PKEY_RSA , - 1 , C .GO_EVP_PKEY_CTRL_MD , 0 , unsafe .Pointer (md )) != 1 {
319
+ if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , C .GO_EVP_PKEY_RSA , - 1 , C .GO_EVP_PKEY_CTRL_MD , 0 , unsafe .Pointer (alg . md )) != 1 {
310
320
return nil , newOpenSSLError ("EVP_PKEY_CTX_ctrl failed" )
311
321
}
312
322
// setPadding must happen after setting EVP_PKEY_CTRL_MD.
@@ -322,11 +332,11 @@ func setupEVP(withKey withKeyFunc, padding C.int,
322
332
case C .GO_RSA_PKCS1_PADDING :
323
333
if ch != 0 {
324
334
// We support unhashed messages.
325
- md := cryptoHashToMD (ch )
326
- if md == nil {
335
+ alg := loadHash (ch )
336
+ if alg == nil {
327
337
return nil , errors .New ("crypto/rsa: unsupported hash function" )
328
338
}
329
- if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 , - 1 , C .GO_EVP_PKEY_CTRL_MD , 0 , unsafe .Pointer (md )) != 1 {
339
+ if C .go_openssl_EVP_PKEY_CTX_ctrl (ctx , - 1 , - 1 , C .GO_EVP_PKEY_CTRL_MD , 0 , unsafe .Pointer (alg . md )) != 1 {
330
340
return nil , newOpenSSLError ("EVP_PKEY_CTX_ctrl failed" )
331
341
}
332
342
if err := setPadding (); err != nil {
@@ -441,8 +451,8 @@ func evpVerify(withKey withKeyFunc, padding C.int, saltLen C.int, h crypto.Hash,
441
451
}
442
452
443
453
func evpHashSign (withKey withKeyFunc , h crypto.Hash , msg []byte ) ([]byte , error ) {
444
- md := cryptoHashToMD (h )
445
- if md == nil {
454
+ alg := loadHash (h )
455
+ if alg == nil {
446
456
return nil , errors .New ("unsupported hash function: " + strconv .Itoa (int (h )))
447
457
}
448
458
var out []byte
@@ -453,7 +463,7 @@ func evpHashSign(withKey withKeyFunc, h crypto.Hash, msg []byte) ([]byte, error)
453
463
}
454
464
defer C .go_openssl_EVP_MD_CTX_free (ctx )
455
465
if withKey (func (key C.GO_EVP_PKEY_PTR ) C.int {
456
- return C .go_openssl_EVP_DigestSignInit (ctx , nil , md , nil , key )
466
+ return C .go_openssl_EVP_DigestSignInit (ctx , nil , alg . md , nil , key )
457
467
}) != 1 {
458
468
return nil , newOpenSSLError ("EVP_DigestSignInit failed" )
459
469
}
@@ -473,8 +483,8 @@ func evpHashSign(withKey withKeyFunc, h crypto.Hash, msg []byte) ([]byte, error)
473
483
}
474
484
475
485
func evpHashVerify (withKey withKeyFunc , h crypto.Hash , msg , sig []byte ) error {
476
- md := cryptoHashToMD (h )
477
- if md == nil {
486
+ alg := loadHash (h )
487
+ if alg == nil {
478
488
return errors .New ("unsupported hash function: " + strconv .Itoa (int (h )))
479
489
}
480
490
ctx := C .go_openssl_EVP_MD_CTX_new ()
@@ -483,7 +493,7 @@ func evpHashVerify(withKey withKeyFunc, h crypto.Hash, msg, sig []byte) error {
483
493
}
484
494
defer C .go_openssl_EVP_MD_CTX_free (ctx )
485
495
if withKey (func (key C.GO_EVP_PKEY_PTR ) C.int {
486
- return C .go_openssl_EVP_DigestVerifyInit (ctx , nil , md , nil , key )
496
+ return C .go_openssl_EVP_DigestVerifyInit (ctx , nil , alg . md , nil , key )
487
497
}) != 1 {
488
498
return newOpenSSLError ("EVP_DigestVerifyInit failed" )
489
499
}
0 commit comments