221 lines
8.1 KiB
Julia
221 lines
8.1 KiB
Julia
|
"The size of an account object in bytes"
|
||
|
account_size() = ccall((:olm_account_size, libolm), Csize_t, ())
|
||
|
|
||
|
"""Initialise an account object using the supplied memory
|
||
|
The supplied memory must be at least olm_account_size() bytes"""
|
||
|
function account()
|
||
|
memory = allocate(account_size())
|
||
|
ccall((:olm_account, libolm), Ptr{Cvoid}, (Ptr{Cvoid},), memory)
|
||
|
end
|
||
|
|
||
|
"The number of random bytes needed to create an account."
|
||
|
create_account_random_length(a::OlmAccount) =
|
||
|
ccall((:olm_create_account_random_length, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},), a.ptr)
|
||
|
|
||
|
"""Creates a new account. Returns olm_error() on failure. If there weren't
|
||
|
enough random bytes then olm_account_last_error() will be
|
||
|
NOT_ENOUGH_RANDOM"""
|
||
|
function create(a::OlmAccount)
|
||
|
random_length = create_account_random_length(a)
|
||
|
random = allocate(random_length)
|
||
|
res = ccall((:olm_create_account, libolm), Csize_t,
|
||
|
(Ptr{Cvoid}, Ptr{Cvoid}, Csize_t),
|
||
|
a.ptr, random, random_length)
|
||
|
return res != error
|
||
|
end
|
||
|
|
||
|
function OlmAccount()
|
||
|
a = OlmAccount(account())
|
||
|
create(a)
|
||
|
a
|
||
|
end
|
||
|
|
||
|
"""Loads an account from a pickled base64 string. Decrypts the account using the
|
||
|
supplied key. Returns olm_error() on failure. If the key doesn't match the one
|
||
|
used to encrypt the account then olm_account_last_error() will be
|
||
|
"BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
|
||
|
olm_account_last_error() will be "INVALID_BASE64". The input pickled buffer is
|
||
|
destroyed"""
|
||
|
function unpickle!(a::OlmAccount, pickle::Vector{Char}, passphrase::Vector{Char})
|
||
|
memlength = pickle_length(a)
|
||
|
res = ccall((:olm_unpickle_account, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},
|
||
|
Ptr{Cvoid}, Csize_t,
|
||
|
Ptr{Cvoid}, Csize_t,),
|
||
|
a.ptr,
|
||
|
passphrase, length(passphrase),
|
||
|
collect(pickle), length(pickle))
|
||
|
# If passphrase is empty, pickle is not encrypted, delete it.
|
||
|
# Else, deleting the key is fine
|
||
|
erase!(length(passphrase) == 0 ? passphrase : pickle, func = rand)
|
||
|
if res == error
|
||
|
throw(last_error(a))
|
||
|
else
|
||
|
a
|
||
|
end
|
||
|
end
|
||
|
|
||
|
"""Initialize a pickled account. Note htat passphrase is cleared after use.
|
||
|
"""
|
||
|
function OlmAccount(pickle::Vector{Char}, passphrase::Vector{Char})
|
||
|
a = OlmAccount(account())
|
||
|
unpickle!(a, pickle, passphrase)
|
||
|
end
|
||
|
|
||
|
"""A null terminated string describing the most recent error to happen to an
|
||
|
account"""
|
||
|
last_error(a::OlmAccount) =
|
||
|
ccall((:olm_account_last_error, libolm), Cstring, (Ptr{Cvoid},), a.ptr) |>
|
||
|
unsafe_string
|
||
|
|
||
|
"""A null terminated string describing the most recent error to happen to a
|
||
|
session"""
|
||
|
last_error(s::OlmSession) =
|
||
|
ccall((:olm_session_last_error, libolm), Cstring, (Ptr{Cvoid},), s.ptr) |>
|
||
|
unsafe_string
|
||
|
|
||
|
"Returns the number of bytes needed to store an account"
|
||
|
pickle_length(a::OlmAccount) =
|
||
|
ccall((:olm_pickle_account_length, libolm), Csize_t, (Ptr{Cvoid},), a.ptr)
|
||
|
|
||
|
"Returns the number of bytes needed to store a session"
|
||
|
pickle_length(s::OlmSession) =
|
||
|
ccall((:olm_pickle_session_length, libolm), Csize_t, (Ptr{Cvoid},), s.ptr)
|
||
|
|
||
|
"""Stores an account as a base64 string. Encrypts the account using the
|
||
|
supplied key. Returns the length of the pickled account on success.
|
||
|
Returns olm_error() on failure. If the pickle output buffer
|
||
|
is smaller than olm_pickle_account_length() then olm_account_last_error()
|
||
|
will be "OUTPUT_BUFFER_TOO_SMALL"."""
|
||
|
function pickle!(a::OlmAccount, passphrase::Vector{Char})
|
||
|
memlength = pickle_length(a)
|
||
|
memory = allocate(memlength)
|
||
|
res = ccall((:olm_pickle_account, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},
|
||
|
Ptr{Cvoid}, Csize_t,
|
||
|
Ptr{Cvoid}, Csize_t,),
|
||
|
a.ptr,
|
||
|
passphrase, length(passphrase),
|
||
|
memory, memlength)
|
||
|
# zero(Char) does not extists, but rand does
|
||
|
erase!(passphrase, func = rand)
|
||
|
# Check results
|
||
|
if res == memlength
|
||
|
memory
|
||
|
else
|
||
|
throw(last_error(a))
|
||
|
end
|
||
|
end
|
||
|
pickle!(a::OlmAccount) = pickle!(a, Char[])
|
||
|
|
||
|
# Base.getpass("Account encryption key")
|
||
|
|
||
|
"The size of the output buffer needed to hold the identity keys"
|
||
|
account_identity_keys_length(a::OlmAccount) =
|
||
|
ccall((:olm_account_identity_keys_length, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},), a.ptr)
|
||
|
|
||
|
"The largest number of one time keys this account can store."
|
||
|
max_number_of_one_time_keys() =
|
||
|
ccall((:olm_account_max_number_of_one_time_keys, libolm), Csize_t, ())
|
||
|
|
||
|
"""The number of random bytes needed to generate a given number of new one time
|
||
|
keys."""
|
||
|
function generate_one_time_keys_random_length(a::OlmAccount, count::Integer)
|
||
|
ccall((:olm_account_generate_one_time_keys_random_length, libolm), Csize_t,
|
||
|
(Ptr{Cvoid}, Csize_t),
|
||
|
a.ptr, count)
|
||
|
end
|
||
|
|
||
|
"""Marks the current set of one time keys as being published."""
|
||
|
mark_keys_as_published(a::OlmAccount) =
|
||
|
ccall((:olm_account_mark_keys_as_published, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},), a.ptr)
|
||
|
|
||
|
"The length of an ed25519 signature encoded as base64."
|
||
|
signature_length(a::OlmAccount) =
|
||
|
ccall((:olm_account_signature_length, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},), a.ptr)
|
||
|
|
||
|
"The size of the output buffer needed to hold the one time keys"
|
||
|
one_time_keys_length(a::OlmAccount) =
|
||
|
ccall((:olm_account_one_time_keys_length, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},), a.ptr)
|
||
|
|
||
|
"""Writes the public parts of the identity keys for the account into the
|
||
|
identity_keys output buffer. Returns olm_error() on failure. If the
|
||
|
identity_keys buffer was too small then olm_account_last_error() will be
|
||
|
OUTPUT_BUFFER_TOO_SMALL."""
|
||
|
function identity_keys(a::OlmAccount)
|
||
|
identity_key_length = identity_keys_length(a)
|
||
|
identity_keys = allocate(identity_key_length)
|
||
|
res = ccall((:olm_account_identity_keys, libolm), Csize_t,
|
||
|
(Ptr{Cvoid}, Ptr{Cvoid}, Csize_t),
|
||
|
a.ptr, identity_keys, identity_key_length)
|
||
|
identity_keys |> String
|
||
|
end
|
||
|
|
||
|
"""Signs a message with the ed25519 key for this account. Returns olm_error() on
|
||
|
failure. If the signature buffer was too small then olm_account_last_error()
|
||
|
will be OUTPUT_BUFFER_TOO_SMALL"""
|
||
|
function sign!(a::OlmAccount, message)
|
||
|
siglength = signature_length(a)
|
||
|
output = allocate(siglength)
|
||
|
ccall((:olm_account_sign, libolm), Csize_t,
|
||
|
(Ptr{Cvoid},
|
||
|
Ptr{Cvoid}, Csize_t,
|
||
|
Ptr{Cvoid}, Csize_t),
|
||
|
a.ptr,
|
||
|
message, length(message),
|
||
|
output, siglength)
|
||
|
erase!(message)
|
||
|
String(deepcopy(output))
|
||
|
end
|
||
|
|
||
|
"""Generates a number of new one time keys. If the total number of keys stored
|
||
|
by this account exceeds max_number_of_one_time_keys() then the old keys are
|
||
|
discarded. Returns olm_error() on error. If the number of random bytes is
|
||
|
too small then olm_account_last_error() will be NOT_ENOUGH_RANDOM."""
|
||
|
function generate_one_time_keys(a::OlmAccount, count::Integer)
|
||
|
0 < count <= max_number_of_one_time_keys() ||
|
||
|
throw("Error: invalid number of keys")
|
||
|
len = generate_one_time_keys_random_length(a, count)
|
||
|
random = rallocate(len)
|
||
|
res = ccall((:olm_account_generate_one_time_keys, libolm), Csize_t,
|
||
|
(Ptr{Cvoid}, Csize_t, Ptr{Cvoid}, Csize_t),
|
||
|
a.ptr, count, random, len)
|
||
|
erase!(random)
|
||
|
Int(res)
|
||
|
end
|
||
|
|
||
|
"""Writes the public parts of the unpublished one time keys for the account into
|
||
|
the one_time_keys output buffer.
|
||
|
<p>
|
||
|
The returned data is a JSON-formatted object with the single property
|
||
|
<tt>curve25519</tt>, which is itself an object mapping key id to
|
||
|
base64-encoded Curve25519 key. For example:
|
||
|
<pre>
|
||
|
{
|
||
|
curve25519: {
|
||
|
"AAAAAA": "wo76WcYtb0Vk/pBOdmduiGJ0wIEjW4IBMbbQn7aSnTo",
|
||
|
"AAAAAB": "LRvjo46L1X2vx69sS9QNFD29HWulxrmW11Up5AfAjgU"
|
||
|
}
|
||
|
}
|
||
|
</pre>
|
||
|
Returns olm_error() on failure.
|
||
|
<p>
|
||
|
If the one_time_keys buffer was too small then olm_account_last_error()
|
||
|
will be "OUTPUT_BUFFER_TOO_SMALL"."""
|
||
|
function one_time_keys(a::OlmAccount)
|
||
|
one_time_keys_len = one_time_keys_length(a)
|
||
|
one_time_keys = allocate(one_time_keys_len)
|
||
|
res = ccall((:olm_account_one_time_keys, libolm), Csize_t,
|
||
|
(Ptr{Cvoid}, Ptr{Cvoid}, Csize_t),
|
||
|
a.ptr, one_time_keys, one_time_keys_len)
|
||
|
if res == error
|
||
|
throw(last_error(a))
|
||
|
end
|
||
|
JSON.parse(String(deepcopy(one_time_keys)))
|
||
|
end
|