func (state fastGCMState) Seal(dst, nonce, plaintext, data []byte) []byte { rawenc := make([]byte, len(plaintext)) sched := (*_Ctype_gcm_state)(unsafe.Pointer(&state[0])) FASSERT(C.gcm_reset(sched) == C.CRYPT_OK) FASSERT(C.gcm_add_iv(sched, unsafe_bytes(nonce), 12) == C.CRYPT_OK) C.gcm_add_aad(sched, nil, 0) FASSERT(C.gcm_process(sched, unsafe_bytes(plaintext), C.ulong(len(plaintext)), unsafe_bytes(rawenc), C.GCM_ENCRYPT) == C.CRYPT_OK) tag := buf.Alloc() thing := C.ulong(16) FASSERT(C.gcm_done(sched, unsafe_bytes(tag), &thing) == C.CRYPT_OK) rawenc = append(rawenc, tag[:int(thing)]...) buf.Free(tag) return append(dst, rawenc...) }
func (state fastGCMState) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { rawpt := make([]byte, len(ciphertext)-16) sched := (*_Ctype_gcm_state)(unsafe.Pointer(&state[0])) FASSERT(C.gcm_reset(sched) == C.CRYPT_OK) FASSERT(C.gcm_add_iv(sched, unsafe_bytes(nonce), 12) == C.CRYPT_OK) FASSERT(C.gcm_add_aad(sched, nil, 0) == C.CRYPT_OK) FASSERT(C.gcm_process(sched, unsafe_bytes(rawpt), C.ulong(len(rawpt)), unsafe_bytes(ciphertext), C.GCM_DECRYPT) == C.CRYPT_OK) tag := buf.Alloc() thing := C.ulong(16) C.gcm_done(sched, unsafe_bytes(tag), &thing) if subtle.ConstantTimeCompare(tag[:int(thing)], ciphertext[len(rawpt):]) != 1 { return nil, errors.New("WTF! HASH OF MISMATCHINGS!") } buf.Free(tag) return append(dst, rawpt...), nil }