Skip to content

Commit 0d4c1bf

Browse files
authored
add:SealWithRandomNonce method (#279)
* add:SealWithRandomNonce method * address pr comments
1 parent c494c21 commit 0d4c1bf

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

cipher.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ type cipherGCM struct {
325325
}
326326

327327
const (
328+
aesBlockSize = 16
328329
gcmTagSize = 16
329330
gcmStandardNonceSize = 12
330331
// TLS 1.2 additional data is constructed as:
@@ -480,6 +481,56 @@ func (g *cipherGCM) Seal(dst, nonce, plaintext, aad []byte) []byte {
480481
return ret
481482
}
482483

484+
func (g *cipherGCM) SealWithRandomNonce(out, nonce, plaintext, aad []byte) {
485+
if uint64(len(plaintext)) > uint64((1<<32)-2)*aesBlockSize {
486+
panic("crypto/cipher: message too large for GCM")
487+
}
488+
if len(nonce) != gcmStandardNonceSize {
489+
panic("crypto/cipher: incorrect nonce length given to GCMWithRandomNonce")
490+
}
491+
if len(out) != len(plaintext)+gcmTagSize {
492+
panic("crypto/cipher: incorrect output length given to GCMWithRandomNonce")
493+
}
494+
if inexactOverlap(out, plaintext) {
495+
panic("crypto/cipher: invalid buffer overlap of output and input")
496+
}
497+
if anyOverlap(out, aad) {
498+
panic("crypto/cipher: invalid buffer overlap of output and additional data")
499+
}
500+
501+
if g.tls != cipherGCMTLSNone {
502+
panic("cipher: encryption failed")
503+
}
504+
505+
RandReader.Read(nonce)
506+
ctx, err := newCipherCtx(g.c.kind, cipherModeGCM, cipherOpNone, g.c.key, nil)
507+
if err != nil {
508+
panic(err)
509+
}
510+
defer ossl.EVP_CIPHER_CTX_free(ctx)
511+
512+
if _, err := ossl.EVP_EncryptInit_ex(ctx, nil, nil, nil, base(nonce)); err != nil {
513+
panic(err)
514+
}
515+
var outl, discard int32
516+
if _, err := ossl.EVP_EncryptUpdate(ctx, nil, &discard, baseNeverEmpty(aad), int32(len(aad))); err != nil {
517+
panic(err)
518+
}
519+
if _, err := ossl.EVP_EncryptUpdate(ctx, base(out), &outl, baseNeverEmpty(plaintext), int32(len(plaintext))); err != nil {
520+
panic(err)
521+
}
522+
if len(plaintext) != int(outl) {
523+
panic("cipher: incorrect length returned from GCM EncryptUpdate")
524+
}
525+
if _, err := ossl.EVP_EncryptFinal_ex(ctx, base(out[outl:]), &discard); err != nil {
526+
panic(err)
527+
}
528+
if _, err := ossl.EVP_CIPHER_CTX_ctrl(ctx, ossl.EVP_CTRL_GCM_GET_TAG, 16, unsafe.Pointer(base(out[outl:]))); err != nil {
529+
panic(err)
530+
}
531+
runtime.KeepAlive(g)
532+
}
533+
483534
var errOpen = errors.New("cipher: message authentication failed")
484535

485536
func (g *cipherGCM) Open(dst, nonce, ciphertext, aad []byte) (_ []byte, err error) {

0 commit comments

Comments
 (0)