-
Notifications
You must be signed in to change notification settings - Fork 19
Add support for CSHAKE #243
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
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
393b366
implement CSHAKE support
qmuntal 4667b2e
fix shake sizes
qmuntal a44d077
formatting
qmuntal 1592b8e
fix constructors
qmuntal 278fbd4
simplify supportsSHAKE
qmuntal dc537e2
don't set EVP_MD_CTRL_XOF_LEN
qmuntal 1526cf8
set xor_len
qmuntal cff0bbb
cache xof_len
qmuntal 6b09b11
improve test hierarchy
qmuntal dc77acd
fix tests
qmuntal bea8a34
fix reset
qmuntal 5e3d1cc
fix shakeOneShot
qmuntal 369bd5d
fix shakeOneShot
qmuntal d0724f7
Merge remote-tracking branch 'upstream/v2' into cshake
gdams cf9bc46
add case to check header
gdams c76a425
refactor CI
gdams 09c016b
Merge remote-tracking branch 'upstream/v2' into cshake
gdams 5bc6d8b
quim feedback
gdams File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,219 @@ | ||
| //go:build !cmd_go_bootstrap && (cgo || goexperiment.ms_nocgo_opensslcrypto) | ||
|
|
||
| package openssl | ||
|
|
||
| import ( | ||
| "runtime" | ||
| "strconv" | ||
| "sync" | ||
|
|
||
| "github.com/golang-fips/openssl/v2/internal/ossl" | ||
| ) | ||
|
|
||
| // shakeOneShot applies the SHAKE extendable output function to data and | ||
| // writes the output to out. | ||
| func shakeOneShot(secuirtyBits int, data []byte, out []byte) { | ||
| // Can't use EVP_Digest because it doesn't support output lengths | ||
| // larger than the block size, while crypto/sha3 supports any length. | ||
| alg := loadShake(secuirtyBits) | ||
| if alg == nil { | ||
| panic("openssl: unsupported SHAKE" + strconv.Itoa(secuirtyBits) + " function") | ||
| } | ||
| ctx, err := ossl.EVP_MD_CTX_new() | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| defer ossl.EVP_MD_CTX_free(ctx) | ||
| if _, err := ossl.EVP_DigestInit_ex(ctx, alg.md, nil); err != nil { | ||
| panic(err) | ||
| } | ||
| if _, err := ossl.EVP_DigestUpdate(ctx, data); err != nil { | ||
| panic(err) | ||
| } | ||
| if _, err := ossl.EVP_DigestFinalXOF(ctx, out, len(out)); err != nil { | ||
| panic(err) | ||
| } | ||
| } | ||
|
|
||
| // SumSHAKE128 applies the SHAKE128 extendable output function to data and | ||
| // returns an output of the given length in bytes. | ||
| func SumSHAKE128(data []byte, length int) []byte { | ||
| out := make([]byte, length) | ||
| shakeOneShot(128, data, out) | ||
| return out | ||
| } | ||
|
|
||
| // SumSHAKE256 applies the SHAKE256 extendable output function to data and | ||
| // returns an output of the given length in bytes. | ||
| func SumSHAKE256(data []byte, length int) []byte { | ||
| out := make([]byte, length) | ||
| shakeOneShot(256, data, out) | ||
| return out | ||
| } | ||
|
|
||
| // SupportsSHAKE returns true if the SHAKE extendable output functions | ||
| // with the given securityBits are supported. | ||
| func SupportsSHAKE(securityBits int) bool { | ||
| if vMajor == 1 || (vMajor == 3 && vMinor < 3) { | ||
| // SHAKE MD's are supported since OpenSSL 1.1.1, | ||
| // but EVP_DigestSqueeze is only supported since 3.3, | ||
| // and we need it to implement [sha3.SHAKE]. | ||
| return false | ||
| } | ||
| return loadShake(securityBits) != nil | ||
| } | ||
|
|
||
| // SupportsCSHAKE returns true if the CSHAKE extendable output functions | ||
| // with the given securityBits are supported. | ||
| func SupportsCSHAKE(securityBits int) bool { | ||
| // OpenSSL tracker issue https://github.com/openssl/openssl/issues/28358 | ||
| return false | ||
| } | ||
|
|
||
| // SHAKE is an instance of a SHAKE extendable output function. | ||
| type SHAKE struct { | ||
| alg *shakeAlgorithm | ||
| ctx ossl.EVP_MD_CTX_PTR | ||
| lastXofLen int | ||
| } | ||
|
|
||
| // NewSHAKE128 creates a new SHAKE128 XOF. | ||
| func NewSHAKE128() *SHAKE { | ||
| return newSHAKE(128) | ||
| } | ||
|
|
||
| // NewSHAKE256 creates a new SHAKE256 XOF. | ||
| func NewSHAKE256() *SHAKE { | ||
| return newSHAKE(256) | ||
| } | ||
|
|
||
| // NewCSHAKE128 creates a new cSHAKE128 XOF. | ||
| // | ||
| // N is used to define functions based on cSHAKE, it can be empty when plain | ||
| // cSHAKE is desired. S is a customization byte string used for domain | ||
| // separation. When N and S are both empty, this is equivalent to NewSHAKE128. | ||
| func NewCSHAKE128(N, S []byte) *SHAKE { | ||
| if len(N) == 0 && len(S) == 0 { | ||
| return NewSHAKE128() | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| // NewCSHAKE256 creates a new cSHAKE256 XOF. | ||
| // | ||
| // N is used to define functions based on cSHAKE, it can be empty when plain | ||
| // cSHAKE is desired. S is a customization byte string used for domain | ||
| // separation. When N and S are both empty, this is equivalent to NewSHAKE256. | ||
| func NewCSHAKE256(N, S []byte) *SHAKE { | ||
| if len(N) == 0 && len(S) == 0 { | ||
| return NewSHAKE256() | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func newSHAKE(securityBits int) *SHAKE { | ||
| alg := loadShake(securityBits) | ||
| if alg == nil { | ||
| panic("openssl: unsupported SHAKE" + strconv.Itoa(securityBits) + " function") | ||
| } | ||
| ctx, err := ossl.EVP_MD_CTX_new() | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| if _, err := ossl.EVP_DigestInit_ex(ctx, alg.md, nil); err != nil { | ||
| ossl.EVP_MD_CTX_free(ctx) | ||
| panic(err) | ||
| } | ||
| s := &SHAKE{alg: alg, ctx: ctx} | ||
| runtime.SetFinalizer(s, (*SHAKE).finalize) | ||
| return s | ||
| } | ||
|
|
||
| func (s *SHAKE) finalize() { | ||
| ossl.EVP_MD_CTX_free(s.ctx) | ||
| } | ||
|
|
||
| // Write absorbs more data into the XOF's state. | ||
| // | ||
| // It panics if any output has already been read. | ||
| func (s *SHAKE) Write(p []byte) (n int, err error) { | ||
| defer runtime.KeepAlive(s) | ||
| if len(p) == 0 { | ||
| return 0, nil | ||
| } | ||
| if _, err := ossl.EVP_DigestUpdate(s.ctx, p); err != nil { | ||
| panic(err) | ||
| } | ||
| return len(p), nil | ||
| } | ||
|
|
||
| // Read squeezes more output from the XOF. | ||
| // | ||
| // Any call to Write after a call to Read will panic. | ||
| func (s *SHAKE) Read(p []byte) (n int, err error) { | ||
| defer runtime.KeepAlive(s) | ||
| if len(p) == 0 { | ||
| return 0, nil | ||
| } | ||
| if len(p) != s.lastXofLen { | ||
| if _, err := ossl.EVP_MD_CTX_ctrl(s.ctx, ossl.EVP_MD_CTRL_XOF_LEN, int32(len(p)), nil); err != nil { | ||
| panic(err) | ||
| } | ||
| s.lastXofLen = len(p) | ||
| } | ||
| if _, err := ossl.EVP_DigestSqueeze(s.ctx, p); err != nil { | ||
| panic(err) | ||
| } | ||
| return len(p), nil | ||
| } | ||
|
|
||
| // Reset resets the XOF to its initial state. | ||
| func (s *SHAKE) Reset() { | ||
| defer runtime.KeepAlive(s) | ||
| if _, err := ossl.EVP_DigestInit_ex(s.ctx, nil, nil); err != nil { | ||
| panic(err) | ||
| } | ||
| s.lastXofLen = 0 | ||
| } | ||
|
|
||
| // BlockSize returns the rate of the XOF. | ||
| func (s *SHAKE) BlockSize() int { | ||
| return s.alg.blockSize | ||
| } | ||
|
|
||
| type shakeAlgorithm struct { | ||
| md ossl.EVP_MD_PTR | ||
| blockSize int | ||
| } | ||
|
|
||
| var cacheSHAKE sync.Map | ||
|
|
||
| // loadShake converts a crypto.Hash to a EVP_MD. | ||
| func loadShake(securityBits int) (alg *shakeAlgorithm) { | ||
| if v, ok := cacheSHAKE.Load(securityBits); ok { | ||
| return v.(*shakeAlgorithm) | ||
| } | ||
| defer func() { | ||
| cacheSHAKE.Store(securityBits, alg) | ||
| }() | ||
|
|
||
| var name cString | ||
| switch securityBits { | ||
| case 128: | ||
| name = _DigestNameSHAKE128 | ||
| case 256: | ||
| name = _DigestNameSHAKE256 | ||
| default: | ||
| return nil | ||
| } | ||
|
|
||
| md, err := ossl.EVP_MD_fetch(nil, name.ptr(), nil) | ||
| if err != nil || md == nil { | ||
| return nil | ||
| } | ||
|
|
||
| alg = new(shakeAlgorithm) | ||
| alg.md = md | ||
| alg.blockSize = int(ossl.EVP_MD_get_block_size(md)) | ||
| return alg | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.