summaryrefslogtreecommitdiff
path: root/src/mongo/gotools/vendor/src/github.com/10gen/openssl/tickets.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/gotools/vendor/src/github.com/10gen/openssl/tickets.go')
-rw-r--r--src/mongo/gotools/vendor/src/github.com/10gen/openssl/tickets.go222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/mongo/gotools/vendor/src/github.com/10gen/openssl/tickets.go b/src/mongo/gotools/vendor/src/github.com/10gen/openssl/tickets.go
new file mode 100644
index 00000000000..a064d38592f
--- /dev/null
+++ b/src/mongo/gotools/vendor/src/github.com/10gen/openssl/tickets.go
@@ -0,0 +1,222 @@
+// 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.
+
+package openssl
+
+// #include "shim.h"
+import "C"
+
+import (
+ "os"
+ "unsafe"
+)
+
+const (
+ KeyNameSize = 16
+)
+
+// TicketCipherCtx describes the cipher that will be used by the ticket store
+// for encrypting the tickets. Engine may be nil if no engine is desired.
+type TicketCipherCtx struct {
+ Cipher *Cipher
+ Engine *Engine
+}
+
+// TicketDigestCtx describes the digest that will be used by the ticket store
+// to authenticate the data. Engine may be nil if no engine is desired.
+type TicketDigestCtx struct {
+ Digest *Digest
+ Engine *Engine
+}
+
+// TicketName is an identifier for the key material for a ticket.
+type TicketName [KeyNameSize]byte
+
+// TicketKey is the key material for a ticket. If this is lost, forward secrecy
+// is lost as it allows decrypting TLS sessions retroactively.
+type TicketKey struct {
+ Name TicketName
+ CipherKey []byte
+ HMACKey []byte
+ IV []byte
+}
+
+// TicketKeyManager is a manager for TicketKeys. It allows one to control the
+// lifetime of tickets, causing renewals and expirations for keys that are
+// created. Calls to the manager are serialized.
+type TicketKeyManager interface {
+ // New should create a brand new TicketKey with a new name.
+ New() *TicketKey
+
+ // Current should return a key that is still valid.
+ Current() *TicketKey
+
+ // Lookup should return a key with the given name, or nil if no name
+ // exists.
+ Lookup(name TicketName) *TicketKey
+
+ // Expired should return if the key with the given name is expired and
+ // should not be used any more.
+ Expired(name TicketName) bool
+
+ // ShouldRenew should return if the key is still ok to use for the current
+ // session, but we should send a new key for the client.
+ ShouldRenew(name TicketName) bool
+}
+
+// TicketStore descibes the encryption and authentication methods the tickets
+// will use along with a key manager for generating and keeping track of the
+// secrets.
+type TicketStore struct {
+ CipherCtx TicketCipherCtx
+ DigestCtx TicketDigestCtx
+ Keys TicketKeyManager
+}
+
+func (t *TicketStore) cipherEngine() *C.ENGINE {
+ if t.CipherCtx.Engine == nil {
+ return nil
+ }
+ return t.CipherCtx.Engine.e
+}
+
+func (t *TicketStore) digestEngine() *C.ENGINE {
+ if t.DigestCtx.Engine == nil {
+ return nil
+ }
+ return t.DigestCtx.Engine.e
+}
+
+const (
+ // instruct to do a handshake
+ ticket_resp_requireHandshake = 0
+ // crypto context is set up correctly
+ ticket_resp_sessionOk = 1
+ // crypto context is ok, but the ticket should be reissued
+ ticket_resp_renewSession = 2
+ // we had a problem that shouldn't fall back to doing a handshake
+ ticket_resp_error = -1
+
+ // asked to create session crypto context
+ ticket_req_newSession = 1
+ // asked to load crypto context for a previous session
+ ticket_req_lookupSession = 0
+)
+
+//export go_ticket_key_cb_thunk
+func go_ticket_key_cb_thunk(p unsafe.Pointer, s *C.SSL, key_name *C.uchar,
+ iv *C.uchar, cctx *C.EVP_CIPHER_CTX, hctx *C.HMAC_CTX, enc C.int) C.int {
+
+ // no panic's allowed. it's super hard to guarantee any state at this point
+ // so just abort everything.
+ defer func() {
+ if err := recover(); err != nil {
+ logger.Critf("openssl: ticket key callback panic'd: %v", err)
+ os.Exit(1)
+ }
+ }()
+
+ ctx := (*Ctx)(p)
+ store := ctx.ticket_store
+ if store == nil {
+ // TODO(jeff): should this be an error condition? it doesn't make sense
+ // to be called if we don't have a store I believe, but that's probably
+ // not worth aborting the handshake which is what I believe returning
+ // an error would do.
+ return ticket_resp_requireHandshake
+ }
+
+ ctx.ticket_store_mu.Lock()
+ defer ctx.ticket_store_mu.Unlock()
+
+ switch enc {
+ case ticket_req_newSession:
+ key := store.Keys.Current()
+ if key == nil {
+ key = store.Keys.New()
+ if key == nil {
+ return ticket_resp_requireHandshake
+ }
+ }
+
+ C.memcpy(
+ unsafe.Pointer(key_name),
+ unsafe.Pointer(&key.Name[0]),
+ KeyNameSize)
+ C.EVP_EncryptInit_ex(
+ cctx,
+ store.CipherCtx.Cipher.ptr,
+ store.cipherEngine(),
+ (*C.uchar)(&key.CipherKey[0]),
+ (*C.uchar)(&key.IV[0]))
+ C.HMAC_Init_ex(
+ hctx,
+ unsafe.Pointer(&key.HMACKey[0]),
+ C.int(len(key.HMACKey)),
+ store.DigestCtx.Digest.ptr,
+ store.digestEngine())
+
+ return ticket_resp_sessionOk
+
+ case ticket_req_lookupSession:
+ var name TicketName
+ C.memcpy(
+ unsafe.Pointer(&name[0]),
+ unsafe.Pointer(key_name),
+ KeyNameSize)
+
+ key := store.Keys.Lookup(name)
+ if key == nil {
+ return ticket_resp_requireHandshake
+ }
+ if store.Keys.Expired(name) {
+ return ticket_resp_requireHandshake
+ }
+
+ C.EVP_DecryptInit_ex(
+ cctx,
+ store.CipherCtx.Cipher.ptr,
+ store.cipherEngine(),
+ (*C.uchar)(&key.CipherKey[0]),
+ (*C.uchar)(&key.IV[0]))
+ C.HMAC_Init_ex(
+ hctx,
+ unsafe.Pointer(&key.HMACKey[0]),
+ C.int(len(key.HMACKey)),
+ store.DigestCtx.Digest.ptr,
+ store.digestEngine())
+
+ if store.Keys.ShouldRenew(name) {
+ return ticket_resp_renewSession
+ }
+
+ return ticket_resp_sessionOk
+
+ default:
+ return ticket_resp_error
+ }
+}
+
+// SetTicketStore sets the ticket store for the context so that clients can do
+// ticket based session resumption. If the store is nil, the
+func (c *Ctx) SetTicketStore(store *TicketStore) {
+ c.ticket_store = store
+
+ if store == nil {
+ C.X_SSL_CTX_set_tlsext_ticket_key_cb(c.ctx, nil)
+ } else {
+ C.X_SSL_CTX_set_tlsext_ticket_key_cb(c.ctx,
+ (*[0]byte)(C.X_SSL_CTX_ticket_key_cb))
+ }
+}