goolm: use constants for pickle lengths when possible

Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
This commit is contained in:
Sumner Evans 2024-10-24 20:34:53 -06:00
commit bc1f09086f
No known key found for this signature in database
16 changed files with 119 additions and 192 deletions

View file

@ -488,14 +488,14 @@ func (a *Account) PickleLibOlm(target []byte) (int, error) {
// PickleLen returns the number of bytes the pickled Account will have.
func (a *Account) PickleLen() int {
length := libolmpickle.PickleUInt32Len(accountPickleVersionLibOLM)
length += a.IdKeys.Ed25519.PickleLen()
length += a.IdKeys.Curve25519.PickleLen()
length += libolmpickle.PickleUInt32Len(uint32(len(a.OTKeys)))
length += (len(a.OTKeys) * (&crypto.OneTimeKey{}).PickleLen())
length += libolmpickle.PickleUInt8Len(a.NumFallbackKeys)
length += (int(a.NumFallbackKeys) * (&crypto.OneTimeKey{}).PickleLen())
length += libolmpickle.PickleUInt32Len(a.NextOneTimeKeyID)
length := libolmpickle.PickleUInt32Length
length += crypto.Ed25519KeyPairPickleLength // IdKeys.Ed25519
length += crypto.Curve25519KeyPairPickleLength // IdKeys.Curve25519
length += libolmpickle.PickleUInt32Length
length += (len(a.OTKeys) * crypto.OneTimeKeyPickleLength)
length += libolmpickle.PickleUInt8Length
length += (int(a.NumFallbackKeys) * crypto.OneTimeKeyPickleLength)
length += libolmpickle.PickleUInt32Length
return length
}

View file

@ -15,7 +15,7 @@ import (
const (
Curve25519KeyLength = curve25519.ScalarSize //The length of the private key.
curve25519PubKeyLength = 32
Curve25519PubKeyLength = 32
)
// Curve25519GenerateKey creates a new curve25519 key pair.
@ -51,6 +51,9 @@ type Curve25519KeyPair struct {
PublicKey Curve25519PublicKey `json:"public,omitempty"`
}
const Curve25519KeyPairPickleLength = Curve25519PubKeyLength + // Public Key
Curve25519KeyLength // Private Key
// B64Encoded returns a base64 encoded string of the public key.
func (c Curve25519KeyPair) B64Encoded() id.Curve25519 {
return c.PublicKey.B64Encoded()
@ -61,10 +64,11 @@ func (c Curve25519KeyPair) SharedSecret(pubKey Curve25519PublicKey) ([]byte, err
return c.PrivateKey.SharedSecret(pubKey)
}
// PickleLibOlm encodes the key pair into target. target has to have a size of at least PickleLen() and is written to from index 0.
// PickleLibOlm encodes the key pair into target. The target has to have a size
// of at least [Curve25519KeyPairPickleLength] and is written to from index 0.
// It returns the number of bytes written.
func (c Curve25519KeyPair) PickleLibOlm(target []byte) (int, error) {
if len(target) < c.PickleLen() {
if len(target) < Curve25519KeyPairPickleLength {
return 0, fmt.Errorf("pickle curve25519 key pair: %w", olm.ErrValueTooShort)
}
written, err := c.PublicKey.PickleLibOlm(target)
@ -95,18 +99,6 @@ func (c *Curve25519KeyPair) UnpickleLibOlm(value []byte) (int, error) {
return read + readPriv, nil
}
// PickleLen returns the number of bytes the pickled key pair will have.
func (c Curve25519KeyPair) PickleLen() int {
lenPublic := c.PublicKey.PickleLen()
var lenPrivate int
if len(c.PrivateKey) != Curve25519KeyLength {
lenPrivate = libolmpickle.PickleBytesLen(make([]byte, Curve25519KeyLength))
} else {
lenPrivate = libolmpickle.PickleBytesLen(c.PrivateKey)
}
return lenPublic + lenPrivate
}
// Curve25519PrivateKey represents the private key for curve25519 usage
type Curve25519PrivateKey []byte
@ -141,29 +133,21 @@ func (c Curve25519PublicKey) B64Encoded() id.Curve25519 {
// PickleLibOlm encodes the public key into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (c Curve25519PublicKey) PickleLibOlm(target []byte) (int, error) {
if len(target) < c.PickleLen() {
if len(target) < Curve25519PubKeyLength {
return 0, fmt.Errorf("pickle curve25519 public key: %w", olm.ErrValueTooShort)
}
if len(c) != curve25519PubKeyLength {
return libolmpickle.PickleBytes(make([]byte, curve25519PubKeyLength), target), nil
if len(c) != Curve25519PubKeyLength {
return libolmpickle.PickleBytes(make([]byte, Curve25519PubKeyLength), target), nil
}
return libolmpickle.PickleBytes(c, target), nil
}
// UnpickleLibOlm decodes the unencryted value and populates the public key accordingly. It returns the number of bytes read.
func (c *Curve25519PublicKey) UnpickleLibOlm(value []byte) (int, error) {
unpickled, readBytes, err := libolmpickle.UnpickleBytes(value, curve25519PubKeyLength)
unpickled, readBytes, err := libolmpickle.UnpickleBytes(value, Curve25519PubKeyLength)
if err != nil {
return 0, err
}
*c = unpickled
return readBytes, nil
}
// PickleLen returns the number of bytes the pickled public key will have.
func (c Curve25519PublicKey) PickleLen() int {
if len(c) != curve25519PubKeyLength {
return libolmpickle.PickleBytesLen(make([]byte, curve25519PubKeyLength))
}
return libolmpickle.PickleBytesLen(c)
}

View file

@ -74,7 +74,7 @@ func TestCurve25519Pickle(t *testing.T) {
//create keypair
keyPair, err := crypto.Curve25519GenerateKey()
assert.NoError(t, err)
target := make([]byte, keyPair.PickleLen())
target := make([]byte, crypto.Curve25519KeyPairPickleLength)
writtenBytes, err := keyPair.PickleLibOlm(target)
assert.NoError(t, err)
assert.Len(t, target, writtenBytes)
@ -92,7 +92,7 @@ func TestCurve25519PicklePubKeyOnly(t *testing.T) {
assert.NoError(t, err)
//Remove privateKey
keyPair.PrivateKey = nil
target := make([]byte, keyPair.PickleLen())
target := make([]byte, crypto.Curve25519KeyPairPickleLength)
writtenBytes, err := keyPair.PickleLibOlm(target)
assert.NoError(t, err)
assert.Len(t, target, writtenBytes)
@ -109,7 +109,7 @@ func TestCurve25519PicklePrivKeyOnly(t *testing.T) {
assert.NoError(t, err)
//Remove public
keyPair.PublicKey = nil
target := make([]byte, keyPair.PickleLen())
target := make([]byte, crypto.Curve25519KeyPairPickleLength)
writtenBytes, err := keyPair.PickleLibOlm(target)
assert.NoError(t, err)
assert.Len(t, target, writtenBytes)

View file

@ -46,6 +46,9 @@ type Ed25519KeyPair struct {
PublicKey Ed25519PublicKey `json:"public,omitempty"`
}
const Ed25519KeyPairPickleLength = ed25519.PublicKeySize + // PublicKey
ed25519.PrivateKeySize // Private Key
// B64Encoded returns a base64 encoded string of the public key.
func (c Ed25519KeyPair) B64Encoded() id.Ed25519 {
return id.Ed25519(base64.RawStdEncoding.EncodeToString(c.PublicKey))
@ -61,10 +64,11 @@ func (c Ed25519KeyPair) Verify(message, givenSignature []byte) bool {
return c.PublicKey.Verify(message, givenSignature)
}
// PickleLibOlm encodes the key pair into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
// PickleLibOlm encodes the key pair into target. target has to have a size of
// at least [Ed25519KeyPairPickleLength] and is written to from index 0. It
// returns the number of bytes written.
func (c Ed25519KeyPair) PickleLibOlm(target []byte) (int, error) {
if len(target) < c.PickleLen() {
if len(target) < Ed25519KeyPairPickleLength {
return 0, fmt.Errorf("pickle ed25519 key pair: %w", olm.ErrValueTooShort)
}
written, err := c.PublicKey.PickleLibOlm(target)
@ -96,18 +100,6 @@ func (c *Ed25519KeyPair) UnpickleLibOlm(value []byte) (int, error) {
return read + readPriv, nil
}
// PickleLen returns the number of bytes the pickled key pair will have.
func (c Ed25519KeyPair) PickleLen() int {
lenPublic := c.PublicKey.PickleLen()
var lenPrivate int
if len(c.PrivateKey) != ed25519.PrivateKeySize {
lenPrivate = libolmpickle.PickleBytesLen(make([]byte, ed25519.PrivateKeySize))
} else {
lenPrivate = libolmpickle.PickleBytesLen(c.PrivateKey)
}
return lenPublic + lenPrivate
}
// Curve25519PrivateKey represents the private key for ed25519 usage. This is just a wrapper.
type Ed25519PrivateKey ed25519.PrivateKey
@ -149,10 +141,11 @@ func (c Ed25519PublicKey) Verify(message, givenSignature []byte) bool {
return ed25519.Verify(ed25519.PublicKey(c), message, givenSignature)
}
// PickleLibOlm encodes the public key into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
// PickleLibOlm encodes the public key into target. target has to have a size
// of at least [ed25519.PublicKeySize] and is written to from index 0. It
// returns the number of bytes written.
func (c Ed25519PublicKey) PickleLibOlm(target []byte) (int, error) {
if len(target) < c.PickleLen() {
if len(target) < ed25519.PublicKeySize {
return 0, fmt.Errorf("pickle ed25519 public key: %w", olm.ErrValueTooShort)
}
if len(c) != ed25519.PublicKeySize {
@ -170,11 +163,3 @@ func (c *Ed25519PublicKey) UnpickleLibOlm(value []byte) (int, error) {
*c = unpickled
return readBytes, nil
}
// PickleLen returns the number of bytes the pickled public key will have.
func (c Ed25519PublicKey) PickleLen() int {
if len(c) != ed25519.PublicKeySize {
return libolmpickle.PickleBytesLen(make([]byte, ed25519.PublicKeySize))
}
return libolmpickle.PickleBytesLen(c)
}

View file

@ -38,7 +38,7 @@ func TestEd25519Pickle(t *testing.T) {
//create keypair
keyPair, err := crypto.Ed25519GenerateKey()
assert.NoError(t, err)
target := make([]byte, keyPair.PickleLen())
target := make([]byte, crypto.Ed25519KeyPairPickleLength)
writtenBytes, err := keyPair.PickleLibOlm(target)
assert.NoError(t, err)
assert.Len(t, target, writtenBytes)
@ -56,7 +56,7 @@ func TestEd25519PicklePubKeyOnly(t *testing.T) {
assert.NoError(t, err)
//Remove privateKey
keyPair.PrivateKey = nil
target := make([]byte, keyPair.PickleLen())
target := make([]byte, crypto.Ed25519KeyPairPickleLength)
writtenBytes, err := keyPair.PickleLibOlm(target)
assert.NoError(t, err)
assert.Len(t, target, writtenBytes)
@ -74,7 +74,7 @@ func TestEd25519PicklePrivKeyOnly(t *testing.T) {
assert.NoError(t, err)
//Remove public
keyPair.PublicKey = nil
target := make([]byte, keyPair.PickleLen())
target := make([]byte, crypto.Ed25519KeyPairPickleLength)
writtenBytes, err := keyPair.PickleLibOlm(target)
assert.NoError(t, err)
assert.Len(t, target, writtenBytes)

View file

@ -17,6 +17,10 @@ type OneTimeKey struct {
Key Curve25519KeyPair `json:"key,omitempty"`
}
const OneTimeKeyPickleLength = libolmpickle.PickleUInt32Length + // ID
libolmpickle.PickleBoolLength + // Published
Curve25519KeyPairPickleLength // Key
// Equal compares the one time key to the given one.
func (otk OneTimeKey) Equal(s OneTimeKey) bool {
if otk.ID != s.ID {
@ -37,7 +41,7 @@ func (otk OneTimeKey) Equal(s OneTimeKey) bool {
// PickleLibOlm encodes the key pair into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (c OneTimeKey) PickleLibOlm(target []byte) (int, error) {
if len(target) < c.PickleLen() {
if len(target) < OneTimeKeyPickleLength {
return 0, fmt.Errorf("pickle one time key: %w", olm.ErrValueTooShort)
}
written := libolmpickle.PickleUInt32(uint32(c.ID), target)
@ -73,15 +77,6 @@ func (c *OneTimeKey) UnpickleLibOlm(value []byte) (int, error) {
return totalReadBytes, nil
}
// PickleLen returns the number of bytes the pickled OneTimeKey will have.
func (c OneTimeKey) PickleLen() int {
length := 0
length += libolmpickle.PickleUInt32Len(c.ID)
length += libolmpickle.PickleBoolLen(c.Published)
length += c.Key.PickleLen()
return length
}
// KeyIDEncoded returns the base64 encoded id.
func (c OneTimeKey) KeyIDEncoded() string {
resSlice := make([]byte, 4)

View file

@ -4,13 +4,16 @@ import (
"encoding/binary"
)
const (
PickleBoolLength = 1
PickleUInt8Length = 1
PickleUInt32Length = 4
)
func PickleUInt8(value uint8, target []byte) int {
target[0] = value
return 1
}
func PickleUInt8Len(value uint8) int {
return 1
}
func PickleBool(value bool, target []byte) int {
if value {
@ -20,9 +23,6 @@ func PickleBool(value bool, target []byte) int {
}
return 1
}
func PickleBoolLen(value bool) int {
return 1
}
func PickleBytes(value, target []byte) int {
return copy(target, value)
@ -36,6 +36,3 @@ func PickleUInt32(value uint32, target []byte) int {
binary.BigEndian.PutUint32(res, value)
return copy(target, res)
}
func PickleUInt32Len(value uint32) int {
return 4
}

View file

@ -24,7 +24,7 @@ func TestPickleUInt32(t *testing.T) {
for curIndex := range values {
response := make([]byte, 4)
resPLen := libolmpickle.PickleUInt32(values[curIndex], response)
assert.Equal(t, libolmpickle.PickleUInt32Len(values[curIndex]), resPLen)
assert.Equal(t, libolmpickle.PickleUInt32Length, resPLen)
assert.Equal(t, expected[curIndex], response)
}
}
@ -41,7 +41,7 @@ func TestPickleBool(t *testing.T) {
for curIndex := range values {
response := make([]byte, 1)
resPLen := libolmpickle.PickleBool(values[curIndex], response)
assert.Equal(t, libolmpickle.PickleBoolLen(values[curIndex]), resPLen)
assert.Equal(t, libolmpickle.PickleBoolLength, resPLen)
assert.Equal(t, expected[curIndex], response)
}
}
@ -58,7 +58,7 @@ func TestPickleUInt8(t *testing.T) {
for curIndex := range values {
response := make([]byte, 1)
resPLen := libolmpickle.PickleUInt8(values[curIndex], response)
assert.Equal(t, libolmpickle.PickleUInt8Len(values[curIndex]), resPLen)
assert.Equal(t, libolmpickle.PickleUInt8Length, resPLen)
assert.Equal(t, expected[curIndex], response)
}
}

View file

@ -22,6 +22,9 @@ const (
protocolVersion = 3
RatchetParts = 4 // number of ratchet parts
RatchetPartLength = 256 / 8 // length of each ratchet part in bytes
RatchetPickleLength = (RatchetParts * RatchetPartLength) + //Data
libolmpickle.PickleUInt32Length // Counter
)
var RatchetCipher = cipher.NewAESSHA256([]byte("MEGOLM_KEYS"))
@ -219,17 +222,10 @@ func (r *Ratchet) UnpickleLibOlm(unpickled []byte) (int, error) {
// PickleLibOlm encodes the ratchet into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (r Ratchet) PickleLibOlm(target []byte) (int, error) {
if len(target) < r.PickleLen() {
if len(target) < RatchetPickleLength {
return 0, fmt.Errorf("pickle account: %w", olm.ErrValueTooShort)
}
written := libolmpickle.PickleBytes(r.Data[:], target)
written += libolmpickle.PickleUInt32(r.Counter, target[written:])
return written, nil
}
// PickleLen returns the number of bytes the pickled ratchet will have.
func (r Ratchet) PickleLen() int {
length := libolmpickle.PickleBytesLen(r.Data[:])
length += libolmpickle.PickleUInt32Len(r.Counter)
return length
}

View file

@ -17,6 +17,9 @@ import (
const (
decryptionPickleVersionJSON uint8 = 1
decryptionPickleVersionLibOlm uint32 = 1
DecryptionPickleLength = libolmpickle.PickleUInt32Length + // Version
crypto.Curve25519KeyPairPickleLength // KeyPair
)
// Decryption is used to decrypt pk messages
@ -124,7 +127,7 @@ func (a *Decryption) UnpickleLibOlm(value []byte) (int, error) {
// Pickle returns a base64 encoded and with key encrypted pickled Decryption using PickleLibOlm().
func (a Decryption) Pickle(key []byte) ([]byte, error) {
pickeledBytes := make([]byte, a.PickleLen())
pickeledBytes := make([]byte, DecryptionPickleLength)
written, err := a.PickleLibOlm(pickeledBytes)
if err != nil {
return nil, err
@ -135,10 +138,11 @@ func (a Decryption) Pickle(key []byte) ([]byte, error) {
return cipher.Pickle(key, pickeledBytes)
}
// PickleLibOlm encodes the Decryption into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
// PickleLibOlm encodes the Decryption into target. target has to have a size
// of at least [DecryptionPickleLength] and is written to from index 0. It
// returns the number of bytes written.
func (a Decryption) PickleLibOlm(target []byte) (int, error) {
if len(target) < a.PickleLen() {
if len(target) < DecryptionPickleLength {
return 0, fmt.Errorf("pickle Decryption: %w", olm.ErrValueTooShort)
}
written := libolmpickle.PickleUInt32(decryptionPickleVersionLibOlm, target)
@ -149,10 +153,3 @@ func (a Decryption) PickleLibOlm(target []byte) (int, error) {
written += writtenKey
return written, nil
}
// PickleLen returns the number of bytes the pickled Decryption will have.
func (a Decryption) PickleLen() int {
length := libolmpickle.PickleUInt32Len(decryptionPickleVersionLibOlm)
length += a.KeyPair.PickleLen()
return length
}

View file

@ -19,6 +19,9 @@ type chainKey struct {
Key crypto.Curve25519PublicKey `json:"key"`
}
const chainKeyPickleLength = crypto.Curve25519PubKeyLength + // Key
libolmpickle.PickleUInt32Length // Index
// advance advances the chain
func (c *chainKey) advance() {
c.Key = crypto.HMACSHA256(c.Key, []byte{chainKeySeed})
@ -44,7 +47,7 @@ func (r *chainKey) UnpickleLibOlm(value []byte) (int, error) {
// PickleLibOlm encodes the chain key into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (r chainKey) PickleLibOlm(target []byte) (int, error) {
if len(target) < r.PickleLen() {
if len(target) < chainKeyPickleLength {
return 0, fmt.Errorf("pickle chain key: %w", olm.ErrValueTooShort)
}
written, err := r.Key.PickleLibOlm(target)
@ -55,13 +58,6 @@ func (r chainKey) PickleLibOlm(target []byte) (int, error) {
return written, nil
}
// PickleLen returns the number of bytes the pickled chain key will have.
func (r chainKey) PickleLen() int {
length := r.Key.PickleLen()
length += libolmpickle.PickleUInt32Len(r.Index)
return length
}
// senderChain is a chain for sending messages
type senderChain struct {
RKey crypto.Curve25519KeyPair `json:"ratchet_key"`
@ -69,6 +65,9 @@ type senderChain struct {
IsSet bool `json:"set"`
}
const senderChainPickleLength = chainKeyPickleLength + // RKey
chainKeyPickleLength // CKey
// newSenderChain returns a sender chain initialized with chainKey and ratchet key pair.
func newSenderChain(key crypto.Curve25519PublicKey, ratchet crypto.Curve25519KeyPair) *senderChain {
return &senderChain{
@ -115,7 +114,7 @@ func (r *senderChain) UnpickleLibOlm(value []byte) (int, error) {
// PickleLibOlm encodes the chain into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (r senderChain) PickleLibOlm(target []byte) (int, error) {
if len(target) < r.PickleLen() {
if len(target) < senderChainPickleLength {
return 0, fmt.Errorf("pickle sender chain: %w", olm.ErrValueTooShort)
}
written, err := r.RKey.PickleLibOlm(target)
@ -130,19 +129,15 @@ func (r senderChain) PickleLibOlm(target []byte) (int, error) {
return written, nil
}
// PickleLen returns the number of bytes the pickled chain will have.
func (r senderChain) PickleLen() int {
length := r.RKey.PickleLen()
length += r.CKey.PickleLen()
return length
}
// senderChain is a chain for receiving messages
type receiverChain struct {
RKey crypto.Curve25519PublicKey `json:"ratchet_key"`
CKey chainKey `json:"chain_key"`
}
const receiverChainPickleLength = crypto.Curve25519PubKeyLength + // Ratchet Key
chainKeyPickleLength // CKey
// newReceiverChain returns a receiver chain initialized with chainKey and ratchet public key.
func newReceiverChain(chain crypto.Curve25519PublicKey, ratchet crypto.Curve25519PublicKey) *receiverChain {
return &receiverChain{
@ -188,7 +183,7 @@ func (r *receiverChain) UnpickleLibOlm(value []byte) (int, error) {
// PickleLibOlm encodes the chain into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (r receiverChain) PickleLibOlm(target []byte) (int, error) {
if len(target) < r.PickleLen() {
if len(target) < receiverChainPickleLength {
return 0, fmt.Errorf("pickle sender chain: %w", olm.ErrValueTooShort)
}
written, err := r.RKey.PickleLibOlm(target)
@ -203,19 +198,15 @@ func (r receiverChain) PickleLibOlm(target []byte) (int, error) {
return written, nil
}
// PickleLen returns the number of bytes the pickled chain will have.
func (r receiverChain) PickleLen() int {
length := r.RKey.PickleLen()
length += r.CKey.PickleLen()
return length
}
// messageKey wraps the index and the key of a message
type messageKey struct {
Index uint32 `json:"index"`
Key []byte `json:"key"`
}
const messageKeyPickleLength = messageKeyLength + // Key
libolmpickle.PickleUInt32Length // Index
// UnpickleLibOlm decodes the unencryted value and populates the message key accordingly. It returns the number of bytes read.
func (m *messageKey) UnpickleLibOlm(value []byte) (int, error) {
curPos := 0
@ -237,7 +228,7 @@ func (m *messageKey) UnpickleLibOlm(value []byte) (int, error) {
// PickleLibOlm encodes the message key into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (m messageKey) PickleLibOlm(target []byte) (int, error) {
if len(target) < m.PickleLen() {
if len(target) < messageKeyPickleLength {
return 0, fmt.Errorf("pickle message key: %w", olm.ErrValueTooShort)
}
written := 0
@ -249,10 +240,3 @@ func (m messageKey) PickleLibOlm(target []byte) (int, error) {
written += libolmpickle.PickleUInt32(m.Index, target[written:])
return written, nil
}
// PickleLen returns the number of bytes the pickled message key will have.
func (r messageKey) PickleLen() int {
length := libolmpickle.PickleBytesLen(make([]byte, messageKeyLength))
length += libolmpickle.PickleUInt32Len(r.Index)
return length
}

View file

@ -388,25 +388,25 @@ func (r Ratchet) PickleLibOlm(target []byte) (int, error) {
// PickleLen returns the actual number of bytes the pickled ratchet will have.
func (r Ratchet) PickleLen() int {
length := r.RootKey.PickleLen()
length := crypto.Curve25519PubKeyLength // Root Key
if r.SenderChains.IsSet {
length += libolmpickle.PickleUInt32Len(1)
length += r.SenderChains.PickleLen()
length += libolmpickle.PickleUInt32Length // 1
length += senderChainPickleLength // SenderChains
} else {
length += libolmpickle.PickleUInt32Len(0)
length += libolmpickle.PickleUInt32Length // 0
}
length += libolmpickle.PickleUInt32Len(uint32(len(r.ReceiverChains)))
length += len(r.ReceiverChains) * receiverChain{}.PickleLen()
length += libolmpickle.PickleUInt32Len(uint32(len(r.SkippedMessageKeys)))
length += len(r.SkippedMessageKeys) * skippedMessageKey{}.PickleLen()
length += libolmpickle.PickleUInt32Length // ReceiverChains length
length += len(r.ReceiverChains) * receiverChainPickleLength
length += libolmpickle.PickleUInt32Length // SkippedMessageKeys length
length += len(r.SkippedMessageKeys) * skippedMessageKeyPickleLen
return length
}
// PickleLen returns the minimum number of bytes the pickled ratchet must have.
func (r Ratchet) PickleLenMin() int {
length := r.RootKey.PickleLen()
length += libolmpickle.PickleUInt32Len(0)
length += libolmpickle.PickleUInt32Len(0)
length += libolmpickle.PickleUInt32Len(0)
length := crypto.Curve25519PubKeyLength // Root Key
length += libolmpickle.PickleUInt32Length
length += libolmpickle.PickleUInt32Length
length += libolmpickle.PickleUInt32Length
return length
}

View file

@ -13,6 +13,9 @@ type skippedMessageKey struct {
MKey messageKey `json:"message_key"`
}
const skippedMessageKeyPickleLen = crypto.Curve25519PubKeyLength + // RKey
messageKeyPickleLength // MKey
// UnpickleLibOlm decodes the unencryted value and populates the chain accordingly. It returns the number of bytes read.
func (r *skippedMessageKey) UnpickleLibOlm(value []byte) (int, error) {
curPos := 0
@ -32,7 +35,7 @@ func (r *skippedMessageKey) UnpickleLibOlm(value []byte) (int, error) {
// PickleLibOlm encodes the chain into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (r skippedMessageKey) PickleLibOlm(target []byte) (int, error) {
if len(target) < r.PickleLen() {
if len(target) < skippedMessageKeyPickleLen {
return 0, fmt.Errorf("pickle sender chain: %w", olm.ErrValueTooShort)
}
written, err := r.RKey.PickleLibOlm(target)
@ -46,10 +49,3 @@ func (r skippedMessageKey) PickleLibOlm(target []byte) (int, error) {
written += writtenChain
return written, nil
}
// PickleLen returns the number of bytes the pickled chain will have.
func (r skippedMessageKey) PickleLen() int {
length := r.RKey.PickleLen()
length += r.MKey.PickleLen()
return length
}

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"maunium.net/go/mautrix/crypto/ed25519"
"maunium.net/go/mautrix/crypto/goolm/cipher"
"maunium.net/go/mautrix/crypto/goolm/crypto"
"maunium.net/go/mautrix/crypto/goolm/goolmbase64"
@ -19,6 +20,12 @@ import (
const (
megolmInboundSessionPickleVersionJSON byte = 1
megolmInboundSessionPickleVersionLibOlm uint32 = 2
megolmInboundSessionPickleLength = libolmpickle.PickleUInt32Length + // Version
megolm.RatchetPickleLength + // InitialRatchet
megolm.RatchetPickleLength + // Ratchet
ed25519.PublicKeySize + // SigningKey
libolmpickle.PickleBoolLength // Verified
)
// MegolmInboundSession stores information about the sessions of receive.
@ -246,7 +253,7 @@ func (o *MegolmInboundSession) Pickle(key []byte) ([]byte, error) {
if len(key) == 0 {
return nil, olm.ErrNoKeyProvided
}
pickeledBytes := make([]byte, o.PickleLen())
pickeledBytes := make([]byte, megolmInboundSessionPickleLength)
written, err := o.PickleLibOlm(pickeledBytes)
if err != nil {
return nil, err
@ -260,7 +267,7 @@ func (o *MegolmInboundSession) Pickle(key []byte) ([]byte, error) {
// PickleLibOlm encodes the session into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (o *MegolmInboundSession) PickleLibOlm(target []byte) (int, error) {
if len(target) < o.PickleLen() {
if len(target) < megolmInboundSessionPickleLength {
return 0, fmt.Errorf("pickle MegolmInboundSession: %w", olm.ErrValueTooShort)
}
written := libolmpickle.PickleUInt32(megolmInboundSessionPickleVersionLibOlm, target)
@ -283,16 +290,6 @@ func (o *MegolmInboundSession) PickleLibOlm(target []byte) (int, error) {
return written, nil
}
// PickleLen returns the number of bytes the pickled session will have.
func (o *MegolmInboundSession) PickleLen() int {
length := libolmpickle.PickleUInt32Len(megolmInboundSessionPickleVersionLibOlm)
length += o.InitialRatchet.PickleLen()
length += o.Ratchet.PickleLen()
length += o.SigningKey.PickleLen()
length += libolmpickle.PickleBoolLen(o.SigningKeyVerified)
return length
}
// FirstKnownIndex returns the first message index we know how to decrypt.
func (s *MegolmInboundSession) FirstKnownIndex() uint32 {
return s.InitialRatchet.Counter

View file

@ -21,6 +21,10 @@ import (
const (
megolmOutboundSessionPickleVersion byte = 1
megolmOutboundSessionPickleVersionLibOlm uint32 = 1
MegolmOutboundSessionPickleLength = libolmpickle.PickleUInt32Length + // Version
megolm.RatchetPickleLength + // Ratchet
crypto.Ed25519KeyPairPickleLength // SigningKey
)
// MegolmOutboundSession stores information about the sessions to send.
@ -130,7 +134,7 @@ func (o *MegolmOutboundSession) Pickle(key []byte) ([]byte, error) {
if len(key) == 0 {
return nil, olm.ErrNoKeyProvided
}
pickeledBytes := make([]byte, o.PickleLen())
pickeledBytes := make([]byte, MegolmOutboundSessionPickleLength)
written, err := o.PickleLibOlm(pickeledBytes)
if err != nil {
return nil, err
@ -144,7 +148,7 @@ func (o *MegolmOutboundSession) Pickle(key []byte) ([]byte, error) {
// PickleLibOlm encodes the session into target. target has to have a size of at least PickleLen() and is written to from index 0.
// It returns the number of bytes written.
func (o *MegolmOutboundSession) PickleLibOlm(target []byte) (int, error) {
if len(target) < o.PickleLen() {
if len(target) < MegolmOutboundSessionPickleLength {
return 0, fmt.Errorf("pickle MegolmOutboundSession: %w", olm.ErrValueTooShort)
}
written := libolmpickle.PickleUInt32(megolmOutboundSessionPickleVersionLibOlm, target)
@ -161,14 +165,6 @@ func (o *MegolmOutboundSession) PickleLibOlm(target []byte) (int, error) {
return written, nil
}
// PickleLen returns the number of bytes the pickled session will have.
func (o *MegolmOutboundSession) PickleLen() int {
length := libolmpickle.PickleUInt32Len(megolmOutboundSessionPickleVersionLibOlm)
length += o.Ratchet.PickleLen()
length += o.SigningKey.PickleLen()
return length
}
func (o *MegolmOutboundSession) SessionSharingMessage() ([]byte, error) {
return o.Ratchet.SessionSharingMessage(o.SigningKey)
}

View file

@ -458,22 +458,22 @@ func (o *OlmSession) PickleLibOlm(target []byte) (int, error) {
// PickleLen returns the actual number of bytes the pickled session will have.
func (o *OlmSession) PickleLen() int {
length := libolmpickle.PickleUInt32Len(olmSessionPickleVersionLibOlm)
length += libolmpickle.PickleBoolLen(o.ReceivedMessage)
length += o.AliceIdentityKey.PickleLen()
length += o.AliceBaseKey.PickleLen()
length += o.BobOneTimeKey.PickleLen()
length := libolmpickle.PickleUInt32Length
length += libolmpickle.PickleBoolLength
length += crypto.Curve25519PubKeyLength // AliceIdentityKey
length += crypto.Curve25519PubKeyLength // AliceBaseKey
length += crypto.Curve25519PubKeyLength // BobOneTimeKey
length += o.Ratchet.PickleLen()
return length
}
// PickleLenMin returns the minimum number of bytes the pickled session must have.
func (o *OlmSession) PickleLenMin() int {
length := libolmpickle.PickleUInt32Len(olmSessionPickleVersionLibOlm)
length += libolmpickle.PickleBoolLen(o.ReceivedMessage)
length += o.AliceIdentityKey.PickleLen()
length += o.AliceBaseKey.PickleLen()
length += o.BobOneTimeKey.PickleLen()
length := libolmpickle.PickleUInt32Length
length += libolmpickle.PickleBoolLength
length += crypto.Curve25519PubKeyLength // AliceIdentityKey
length += crypto.Curve25519PubKeyLength // AliceBaseKey
length += crypto.Curve25519PubKeyLength // BobOneTimeKey
length += o.Ratchet.PickleLenMin()
return length
}