// NewWithEngine behaves the same as New but it accepts a pointer to an // `engine.Engine` to setup the engine to use during ctx setup. func NewWithEngine(e *engine.Engine, h func() hash.Hash, key []byte) hash.Hash { if h == nil { return nil } evp := getEVP(h()) if evp == nil { return nil } var eng *C.ENGINE if e != nil { eng = (*C.ENGINE)(e.GetCEngine()) } hm := new(hmac) C.HMAC_CTX_init(&hm.ctx) if C.HMAC_Init_ex(&hm.ctx, unsafe.Pointer(C.CString(string(key))), C.int(len(key)), evp, eng) != 1 { return nil } runtime.SetFinalizer(hm, cleanup) return hm }
func (hm *hmac) Reset() { C.HMAC_Init_ex(&hm.ctx, nil, 0, nil, nil) }
//export ticket_key_cb_thunk func 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 } }