summaryrefslogtreecommitdiff
path: root/src/mongo/gotools/vendor/src/github.com/10gen/openssl/ciphers_gcm.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/gotools/vendor/src/github.com/10gen/openssl/ciphers_gcm.go')
-rw-r--r--src/mongo/gotools/vendor/src/github.com/10gen/openssl/ciphers_gcm.go154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/mongo/gotools/vendor/src/github.com/10gen/openssl/ciphers_gcm.go b/src/mongo/gotools/vendor/src/github.com/10gen/openssl/ciphers_gcm.go
new file mode 100644
index 00000000000..e184c95e5df
--- /dev/null
+++ b/src/mongo/gotools/vendor/src/github.com/10gen/openssl/ciphers_gcm.go
@@ -0,0 +1,154 @@
+// Copyright (C) 2017. See AUTHORS.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !openssl_pre_1.0
+
+package openssl
+
+// #include <openssl/evp.h>
+import "C"
+
+import (
+ "errors"
+ "fmt"
+)
+
+type AuthenticatedEncryptionCipherCtx interface {
+ EncryptionCipherCtx
+
+ // data passed in to ExtraData() is part of the final output; it is
+ // not encrypted itself, but is part of the authenticated data. when
+ // decrypting or authenticating, pass back with the decryption
+ // context's ExtraData()
+ ExtraData([]byte) error
+
+ // use after finalizing encryption to get the authenticating tag
+ GetTag() ([]byte, error)
+}
+
+type AuthenticatedDecryptionCipherCtx interface {
+ DecryptionCipherCtx
+
+ // pass in any extra data that was added during encryption with the
+ // encryption context's ExtraData()
+ ExtraData([]byte) error
+
+ // use before finalizing decryption to tell the library what the
+ // tag is expected to be
+ SetTag([]byte) error
+}
+
+type authEncryptionCipherCtx struct {
+ *encryptionCipherCtx
+}
+
+type authDecryptionCipherCtx struct {
+ *decryptionCipherCtx
+}
+
+func getGCMCipher(blocksize int) (*Cipher, error) {
+ var cipherptr *C.EVP_CIPHER
+ switch blocksize {
+ case 256:
+ cipherptr = C.EVP_aes_256_gcm()
+ case 192:
+ cipherptr = C.EVP_aes_192_gcm()
+ case 128:
+ cipherptr = C.EVP_aes_128_gcm()
+ default:
+ return nil, fmt.Errorf("unknown block size %d", blocksize)
+ }
+ return &Cipher{ptr: cipherptr}, nil
+}
+
+func NewGCMEncryptionCipherCtx(blocksize int, e *Engine, key, iv []byte) (
+ AuthenticatedEncryptionCipherCtx, error) {
+ cipher, err := getGCMCipher(blocksize)
+ if err != nil {
+ return nil, err
+ }
+ ctx, err := newEncryptionCipherCtx(cipher, e, key, nil)
+ if err != nil {
+ return nil, err
+ }
+ if len(iv) > 0 {
+ err := ctx.setCtrl(C.EVP_CTRL_GCM_SET_IVLEN, len(iv))
+ if err != nil {
+ return nil, fmt.Errorf("could not set IV len to %d: %s",
+ len(iv), err)
+ }
+ if 1 != C.EVP_EncryptInit_ex(ctx.ctx, nil, nil, nil,
+ (*C.uchar)(&iv[0])) {
+ return nil, errors.New("failed to apply IV")
+ }
+ }
+ return &authEncryptionCipherCtx{encryptionCipherCtx: ctx}, nil
+}
+
+func NewGCMDecryptionCipherCtx(blocksize int, e *Engine, key, iv []byte) (
+ AuthenticatedDecryptionCipherCtx, error) {
+ cipher, err := getGCMCipher(blocksize)
+ if err != nil {
+ return nil, err
+ }
+ ctx, err := newDecryptionCipherCtx(cipher, e, key, nil)
+ if err != nil {
+ return nil, err
+ }
+ if len(iv) > 0 {
+ err := ctx.setCtrl(C.EVP_CTRL_GCM_SET_IVLEN, len(iv))
+ if err != nil {
+ return nil, fmt.Errorf("could not set IV len to %d: %s",
+ len(iv), err)
+ }
+ if 1 != C.EVP_DecryptInit_ex(ctx.ctx, nil, nil, nil,
+ (*C.uchar)(&iv[0])) {
+ return nil, errors.New("failed to apply IV")
+ }
+ }
+ return &authDecryptionCipherCtx{decryptionCipherCtx: ctx}, nil
+}
+
+func (ctx *authEncryptionCipherCtx) ExtraData(aad []byte) error {
+ if aad == nil {
+ return nil
+ }
+ var outlen C.int
+ if 1 != C.EVP_EncryptUpdate(ctx.ctx, nil, &outlen, (*C.uchar)(&aad[0]),
+ C.int(len(aad))) {
+ return errors.New("failed to add additional authenticated data")
+ }
+ return nil
+}
+
+func (ctx *authDecryptionCipherCtx) ExtraData(aad []byte) error {
+ if aad == nil {
+ return nil
+ }
+ var outlen C.int
+ if 1 != C.EVP_DecryptUpdate(ctx.ctx, nil, &outlen, (*C.uchar)(&aad[0]),
+ C.int(len(aad))) {
+ return errors.New("failed to add additional authenticated data")
+ }
+ return nil
+}
+
+func (ctx *authEncryptionCipherCtx) GetTag() ([]byte, error) {
+ return ctx.getCtrlBytes(C.EVP_CTRL_GCM_GET_TAG, GCM_TAG_MAXLEN,
+ GCM_TAG_MAXLEN)
+}
+
+func (ctx *authDecryptionCipherCtx) SetTag(tag []byte) error {
+ return ctx.setCtrlBytes(C.EVP_CTRL_GCM_SET_TAG, len(tag), tag)
+}