matrix-pretix/vendor/maunium.net/go/mautrix/crypto/olm/verification.go

144 lines
3.5 KiB
Go

//go:build !nosas
// +build !nosas
package olm
// #cgo LDFLAGS: -lolm -lstdc++
// #include <olm/olm.h>
// #include <olm/sas.h>
import "C"
import (
"crypto/rand"
"unsafe"
)
// SAS stores an Olm Short Authentication String (SAS) object.
type SAS struct {
int *C.OlmSAS
mem []byte
}
// NewBlankSAS initializes an empty SAS object.
func NewBlankSAS() *SAS {
memory := make([]byte, sasSize())
return &SAS{
int: C.olm_sas(unsafe.Pointer(&memory[0])),
mem: memory,
}
}
// sasSize is the size of a SAS object in bytes.
func sasSize() uint {
return uint(C.olm_sas_size())
}
// sasRandomLength is the number of random bytes needed to create an SAS object.
func (sas *SAS) sasRandomLength() uint {
return uint(C.olm_create_sas_random_length(sas.int))
}
// NewSAS creates a new SAS object.
func NewSAS() *SAS {
sas := NewBlankSAS()
random := make([]byte, sas.sasRandomLength()+1)
_, err := rand.Read(random)
if err != nil {
panic(NotEnoughGoRandom)
}
r := C.olm_create_sas(
(*C.OlmSAS)(sas.int),
unsafe.Pointer(&random[0]),
C.size_t(len(random)))
if r == errorVal() {
panic(sas.lastError())
} else {
return sas
}
}
// clear clears the memory used to back an SAS object.
func (sas *SAS) clear() uint {
return uint(C.olm_clear_sas(sas.int))
}
// lastError returns the most recent error to happen to an SAS object.
func (sas *SAS) lastError() error {
return convertError(C.GoString(C.olm_sas_last_error(sas.int)))
}
// pubkeyLength is the size of a public key in bytes.
func (sas *SAS) pubkeyLength() uint {
return uint(C.olm_sas_pubkey_length((*C.OlmSAS)(sas.int)))
}
// GetPubkey gets the public key for the SAS object.
func (sas *SAS) GetPubkey() []byte {
pubkey := make([]byte, sas.pubkeyLength())
r := C.olm_sas_get_pubkey(
(*C.OlmSAS)(sas.int),
unsafe.Pointer(&pubkey[0]),
C.size_t(len(pubkey)))
if r == errorVal() {
panic(sas.lastError())
}
return pubkey
}
// SetTheirKey sets the public key of the other user.
func (sas *SAS) SetTheirKey(theirKey []byte) error {
theirKeyCopy := make([]byte, len(theirKey))
copy(theirKeyCopy, theirKey)
r := C.olm_sas_set_their_key(
(*C.OlmSAS)(sas.int),
unsafe.Pointer(&theirKeyCopy[0]),
C.size_t(len(theirKeyCopy)))
if r == errorVal() {
return sas.lastError()
}
return nil
}
// GenerateBytes generates bytes to use for the short authentication string.
func (sas *SAS) GenerateBytes(info []byte, count uint) ([]byte, error) {
infoCopy := make([]byte, len(info))
copy(infoCopy, info)
output := make([]byte, count)
r := C.olm_sas_generate_bytes(
(*C.OlmSAS)(sas.int),
unsafe.Pointer(&infoCopy[0]),
C.size_t(len(infoCopy)),
unsafe.Pointer(&output[0]),
C.size_t(len(output)))
if r == errorVal() {
return nil, sas.lastError()
}
return output, nil
}
// macLength is the size of a message authentication code generated by olm_sas_calculate_mac.
func (sas *SAS) macLength() uint {
return uint(C.olm_sas_mac_length((*C.OlmSAS)(sas.int)))
}
// CalculateMAC generates a message authentication code (MAC) based on the shared secret.
func (sas *SAS) CalculateMAC(input []byte, info []byte) ([]byte, error) {
inputCopy := make([]byte, len(input))
copy(inputCopy, input)
infoCopy := make([]byte, len(info))
copy(infoCopy, info)
mac := make([]byte, sas.macLength())
r := C.olm_sas_calculate_mac(
(*C.OlmSAS)(sas.int),
unsafe.Pointer(&inputCopy[0]),
C.size_t(len(inputCopy)),
unsafe.Pointer(&infoCopy[0]),
C.size_t(len(infoCopy)),
unsafe.Pointer(&mac[0]),
C.size_t(len(mac)))
if r == errorVal() {
return nil, sas.lastError()
}
return mac, nil
}