Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
matrix-org
Olm
Commits
09d8e84c
Commit
09d8e84c
authored
Feb 26, 2015
by
Mark Haines
Browse files
Implement the axlotl ratchet
parent
186df912
Changes
7
Hide whitespace changes
Inline
Side-by-side
include/axolotl/axolotl.hh
View file @
09d8e84c
#include "axolo
l
t/crypto.hh"
#include "axolot
l
/crypto.hh"
#include "axolo
l
t/list.hh"
#include "axolot
l
/list.hh"
namespace
axolotl
{
namespace
axolotl
{
...
@@ -52,7 +52,10 @@ enum struct ErrorCode {
...
@@ -52,7 +52,10 @@ enum struct ErrorCode {
static
std
::
size_t
const
MAX_RECEIVER_CHAINS
=
5
;
static
std
::
size_t
const
MAX_RECEIVER_CHAINS
=
5
;
static
std
::
size_t
const
MAX_SKIPPED_MESSAGE_KEYS
=
40
;
static
std
::
size_t
const
MAX_SKIPPED_MESSAGE_KEYS
=
40
;
struct
KdfInfo
{
struct
KdfInfo
{
std
::
uint8_t
const
*
root_info
;
std
::
size_t
root_info_length
;
std
::
uint8_t
const
*
ratchet_info
;
std
::
uint8_t
const
*
ratchet_info
;
std
::
size_t
ratchet_info_length
;
std
::
size_t
ratchet_info_length
;
std
::
uint8_t
const
*
message_info
;
std
::
uint8_t
const
*
message_info
;
...
@@ -61,15 +64,30 @@ struct KdfInfo {
...
@@ -61,15 +64,30 @@ struct KdfInfo {
struct
Session
{
struct
Session
{
Session
(
KdfInfo
const
&
kdf_info
);
/** A pair of string to feed into the KDF identifing the application */
/** A pair of string to feed into the KDF identifing the application */
KdfInfo
kdf_info
;
KdfInfo
kdf_info
;
/** The last error that happened encypting or decrypting a message */
/** The last error that happened encypting or decrypting a message */
ErrorCode
last_error
;
ErrorCode
last_error
;
SharedKey
root_key
;
SharedKey
root_key
;
List
<
SenderChain
,
1
>
sender_chain
;
List
<
SenderChain
,
1
>
sender_chain
;
List
<
ReceiverChain
,
MAX_RECEIVER_CHAINS
>
rec
i
ever_chains
;
List
<
ReceiverChain
,
MAX_RECEIVER_CHAINS
>
rece
i
ver_chains
;
List
<
SkippedMessageKey
,
MAX_SKIPPED_MESSAGE_KEYS
>
skipped_message_keys
;
List
<
SkippedMessageKey
,
MAX_SKIPPED_MESSAGE_KEYS
>
skipped_message_keys
;
void
initialise_as_bob
(
std
::
uint8_t
const
*
shared_secret
,
std
::
size_t
shared_secret_length
,
Curve25519PublicKey
const
&
their_ratchet_key
);
void
initialise_as_alice
(
std
::
uint8_t
const
*
shared_secret
,
std
::
size_t
shared_secret_length
,
Curve25519KeyPair
const
&
our_ratchet_key
);
std
::
size_t
encrypt_max_output_length
(
std
::
size_t
encrypt_max_output_length
(
std
::
size_t
plaintext_length
std
::
size_t
plaintext_length
);
);
...
...
include/axolotl/crypto.hh
View file @
09d8e84c
...
@@ -15,8 +15,9 @@ struct Curve25519KeyPair : public Curve25519PublicKey {
...
@@ -15,8 +15,9 @@ struct Curve25519KeyPair : public Curve25519PublicKey {
};
};
Curve25519KeyPair
generate_key
(
void
generate_key
(
std
::
uint8_t
const
*
random_32_bytes
std
::
uint8_t
const
*
random_32_bytes
,
Curve25519KeyPair
&
key_pair
);
);
...
...
include/axolotl/list.hh
View file @
09d8e84c
...
@@ -60,6 +60,11 @@ public:
...
@@ -60,6 +60,11 @@ public:
return
pos
;
return
pos
;
}
}
/**
* Make space for an item in the list at the start of the list
*/
T
*
insert
()
{
return
insert
(
begin
());
}
/**
/**
* Insert an item into the list at a given position.
* Insert an item into the list at a given position.
* If inserting the item makes the list longer than max_size then
* If inserting the item makes the list longer than max_size then
...
...
src/axolotl.cpp
View file @
09d8e84c
#include "axolotl/axolotl.hh"
#include "axolotl/axolotl.hh"
#include "axolotl/message.hh"
#include <cstring>
namespace
{
namespace
{
std
::
uint8_t
PROTOCOL_VERSION
=
3
;
std
::
uint8_t
PROTOCOL_VERSION
=
3
;
std
::
size_t
MAC_LENGTH
=
8
;
std
::
size_t
MAC_LENGTH
=
8
;
std
::
size_t
KEY_LENGTH
=
Curve25519PublicKey
::
L
ength
;
std
::
size_t
KEY_LENGTH
=
axolotl
::
Curve25519PublicKey
::
L
ENGTH
;
std
::
uint8_t
MESSAGE_KEY_SEED
[
1
]
=
{
0x01
};
std
::
uint8_t
MESSAGE_KEY_SEED
[
1
]
=
{
0x01
};
std
::
uint8_t
CHAIN_KEY_SEED
[
1
]
=
{
0x02
};
std
::
uint8_t
CHAIN_KEY_SEED
[
1
]
=
{
0x02
};
std
::
size_t
MAX_MESSAGE_GAP
=
2000
;
std
::
size_t
MAX_MESSAGE_GAP
=
2000
;
template
<
typename
T
>
void
unset
(
T
&
value
)
{
std
::
memset
(
&
value
,
0
,
sizeof
(
T
));
}
void
create_chain_key
(
void
create_chain_key
(
axolotl
::
SharedKey
const
&
root_key
,
axolotl
::
SharedKey
const
&
root_key
,
Curve25519KeyPair
const
&
our_key
,
axolotl
::
Curve25519KeyPair
const
&
our_key
,
Curve25519PublicKey
const
&
their_key
,
axolotl
::
Curve25519PublicKey
const
&
their_key
,
std
::
uint8_t
const
*
info
,
std
::
size_t
info_length
,
axolotl
::
KdfInfo
const
&
info
,
SharedSecret
&
new_root_key
,
axolotl
::
SharedKey
&
new_root_key
,
ChainKey
&
new_chain_key
axolotl
::
ChainKey
&
new_chain_key
)
{
)
{
axolotl
::
Shared
Secret
secret
;
axolotl
::
Shared
Key
secret
;
axolotl
::
curve25519_shared_secret
(
our_key
,
their_key
,
secret
);
axolotl
::
curve25519_shared_secret
(
our_key
,
their_key
,
secret
);
std
::
uint8_t
derived_secrets
[
64
];
std
::
uint8_t
derived_secrets
[
64
];
axolotl
::
hkdf_sha256
(
axolotl
::
hkdf_sha256
(
secret
,
sizeof
(
secret
),
secret
,
sizeof
(
secret
),
root_key
,
sizeof
(
root_key
),
root_key
,
sizeof
(
root_key
),
info
,
info_length
,
info
.
ratchet_info
,
info
.
ratchet_
info_length
,
derived_secrets
,
sizeof
(
derived_secrets
)
derived_secrets
,
sizeof
(
derived_secrets
)
);
);
std
::
memcpy
(
new_root_key
,
derived_secrets
,
32
);
std
::
memcpy
(
new_root_key
,
derived_secrets
,
32
);
std
::
memcpy
(
new_chain_key
.
key
,
derived_secrets
+
32
,
32
);
std
::
memcpy
(
new_chain_key
.
key
,
derived_secrets
+
32
,
32
);
new_chain_key
.
index
=
0
;
new_chain_key
.
index
=
0
;
std
::
memset
(
derived_secrets
,
0
,
sizeof
(
derived_secrets
);
unset
(
derived_secrets
);
std
::
mem
set
(
secret
,
0
,
sizeof
(
secret
)
);
un
set
(
secret
);
}
}
void
advance_chain_key
(
void
advance_chain_key
(
ChainKey
const
&
chain_key
,
axolotl
::
ChainKey
const
&
chain_key
,
ChainKey
&
new_chain_key
,
axolotl
::
ChainKey
&
new_chain_key
)
{
)
{
axolotl
::
hmac_sha256
(
axolotl
::
hmac_sha256
(
chain_key
.
key
,
sizeof
(
chain_key
.
key
),
chain_key
.
key
,
sizeof
(
chain_key
.
key
),
...
@@ -49,11 +59,11 @@ void advance_chain_key(
...
@@ -49,11 +59,11 @@ void advance_chain_key(
void
create_message_keys
(
void
create_message_keys
(
ChainKey
const
&
chain_key
,
axolotl
::
ChainKey
const
&
chain_key
,
std
::
uint8_t
const
*
info
,
std
::
size_t
info_length
,
axolotl
::
KdfInfo
const
&
info
,
MessageKey
&
message_key
axolotl
::
MessageKey
&
message_key
)
{
)
{
axolotl
::
Shared
Secret
secret
;
axolotl
::
Shared
Key
secret
;
axolotl
::
hmac_sha256
(
axolotl
::
hmac_sha256
(
chain_key
.
key
,
sizeof
(
chain_key
.
key
),
chain_key
.
key
,
sizeof
(
chain_key
.
key
),
MESSAGE_KEY_SEED
,
sizeof
(
MESSAGE_KEY_SEED
),
MESSAGE_KEY_SEED
,
sizeof
(
MESSAGE_KEY_SEED
),
...
@@ -62,45 +72,43 @@ void create_message_keys(
...
@@ -62,45 +72,43 @@ void create_message_keys(
std
::
uint8_t
derived_secrets
[
80
];
std
::
uint8_t
derived_secrets
[
80
];
axolotl
::
hkdf_sha256
(
axolotl
::
hkdf_sha256
(
secret
,
sizeof
(
secret
),
secret
,
sizeof
(
secret
),
root_key
,
sizeof
(
root_key
)
,
NULL
,
0
,
info
,
info_length
,
info
.
message_info
,
info
.
message_
info_length
,
derived_secrets
,
sizeof
(
derived_secrets
)
derived_secrets
,
sizeof
(
derived_secrets
)
);
);
std
::
memcpy
(
message_key
.
cipher_key
,
derived_secrets
,
32
);
std
::
memcpy
(
message_key
.
cipher_key
.
key
,
derived_secrets
,
32
);
std
::
memcpy
(
message_key
.
mac_key
,
derived_secrets
+
32
,
32
);
std
::
memcpy
(
message_key
.
mac_key
,
derived_secrets
+
32
,
32
);
std
::
memcpy
(
message_key
.
iv
,
derived_secrets
+
64
,
16
);
std
::
memcpy
(
message_key
.
iv
.
iv
,
derived_secrets
+
64
,
16
);
message_key
.
index
=
chain_key
.
index
;
message_key
.
index
=
chain_key
.
index
;
std
::
memset
(
derived_secrets
,
0
,
sizeof
(
derived_secrets
);
unset
(
derived_secrets
);
std
::
mem
set
(
secret
,
0
,
sizeof
(
secret
)
);
un
set
(
secret
);
}
}
bool
verify_mac
(
bool
verify_mac
(
MessageKey
const
&
message_key
,
axolotl
::
MessageKey
const
&
message_key
,
std
::
uint8_t
const
*
input
,
std
::
uint8_t
const
*
input
,
axolotl
::
MessageReader
const
&
reader
axolotl
::
MessageReader
const
&
reader
)
{
)
{
std
::
uint8_t
mac
[
HMAC_SHA256_OUTPUT_LENGTH
];
std
::
uint8_t
mac
[
axolotl
::
HMAC_SHA256_OUTPUT_LENGTH
];
axolotl
::
hmac_sha256
(
axolotl
::
hmac_sha256
(
key
s
.
mac_key
,
sizeof
(
key
s
.
mac_key
),
message_
key
.
mac_key
,
sizeof
(
message_
key
.
mac_key
),
ciphertex
t
,
reader
.
body_length
,
inpu
t
,
reader
.
body_length
,
mac
mac
);
);
bool
result
=
std
::
memcmp
(
mac
,
reader
.
mac
,
MAC_LENGTH
)
==
0
;
bool
result
=
std
::
memcmp
(
mac
,
reader
.
mac
,
MAC_LENGTH
)
==
0
;
std
::
mem
set
(
&
mac
,
0
,
HMAC_SHA256_OUTPUT_LENGTH
);
un
set
(
mac
);
return
result
;
return
result
;
}
}
bool
verify_mac_for_existing_chain
(
bool
verify_mac_for_existing_chain
(
axolotl
::
Session
const
&
session
,
axolotl
::
Session
const
&
session
,
axolotl
::
Receiver
Chain
const
&
chain
,
axolotl
::
Chain
Key
const
&
chain
,
std
::
uint8_t
const
*
input
,
std
::
uint8_t
const
*
input
,
axolotl
::
MessageReader
const
&
reader
axolotl
::
MessageReader
const
&
reader
)
{
)
{
ReceiverChain
new_chain
=
chain
;
if
(
reader
.
counter
<
chain
.
index
)
{
if
(
reader
.
counter
<
chain
.
index
)
{
return
false
;
return
false
;
}
}
...
@@ -110,18 +118,17 @@ bool verify_mac_for_existing_chain(
...
@@ -110,18 +118,17 @@ bool verify_mac_for_existing_chain(
return
false
;
return
false
;
}
}
axolotl
::
ChainKey
new_chain
=
chain
;
while
(
new_chain
.
index
<
reader
.
counter
)
{
while
(
new_chain
.
index
<
reader
.
counter
)
{
advance_chain_key
(
new_chain
,
new_chain
);
advance_chain_key
(
new_chain
,
new_chain
);
}
}
MessageKey
message_key
;
axolotl
::
MessageKey
message_key
;
create_message_keys
(
create_message_keys
(
new_chain
,
session
.
kdf_info
,
message_key
);
new_chain_key
,
sender
.
message_info
,
sender
.
message_info_length
,
message_key
);
bool
result
=
verify_mac
(
message_key
,
input
,
reader
);
bool
result
=
verify_mac
(
message_key
,
input
,
reader
);
std
::
memset
(
&
new_chain
,
0
,
sizeof
(
new_chain
.
ratchet_key
);
unset
(
new_chain
);
return
result
;
return
result
;
}
}
...
@@ -131,8 +138,8 @@ bool verify_mac_for_new_chain(
...
@@ -131,8 +138,8 @@ bool verify_mac_for_new_chain(
std
::
uint8_t
const
*
input
,
std
::
uint8_t
const
*
input
,
axolotl
::
MessageReader
const
&
reader
axolotl
::
MessageReader
const
&
reader
)
{
)
{
SharedSecret
new_root_key
;
axolotl
::
SharedKey
new_root_key
;
ReceiverChain
new_chain
;
axolotl
::
ReceiverChain
new_chain
;
/* They shouldn't move to a new chain until we've sent them a message
/* They shouldn't move to a new chain until we've sent them a message
* acknowledging the last one */
* acknowledging the last one */
...
@@ -144,30 +151,78 @@ bool verify_mac_for_new_chain(
...
@@ -144,30 +151,78 @@ bool verify_mac_for_new_chain(
if
(
reader
.
counter
>
MAX_MESSAGE_GAP
)
{
if
(
reader
.
counter
>
MAX_MESSAGE_GAP
)
{
return
false
;
return
false
;
}
}
std
::
memcpy
(
new_chain
.
ratchet_key
,
reader
.
ratchet_key
,
KEY_LENGTH
);
std
::
memcpy
(
new_chain
.
ratchet_key
.
public_key
,
reader
.
ratchet_key
,
KEY_LENGTH
);
create_chain_key
(
create_chain_key
(
root_key
,
sender_chain
[
0
].
ratchet_key
,
new_chain
.
ratchet_key
,
session
.
root_key
,
session
.
sender_chain
[
0
].
ratchet_key
,
session
.
kdf_info
.
ratchet_
info
,
session
.
kdf_info
.
ratchet_info_length
,
new_chain
.
ratchet_
key
,
session
.
kdf_info
,
new_root_key
,
new_chain
new_root_key
,
new_chain
.
chain_key
);
);
bool
result
=
verify_mac_for_existing_chain
(
bool
result
=
verify_mac_for_existing_chain
(
session
,
new_chain
,
input
,
reader
session
,
new_chain
.
chain_key
,
input
,
reader
);
);
std
::
memset
(
&
new_root_key
,
0
,
sizeof
(
new_root_key
)
)
;
unset
(
new_root_key
);
std
::
memset
(
&
new_chain
,
0
,
sizeof
(
new_chain
.
ratchet_key
);
unset
(
new_chain
);
return
result
;
return
result
;
}
}
}
// namespace
}
// namespace
axolotl
::
Session
::
Session
(
axolotl
::
KdfInfo
const
&
kdf_info
)
:
kdf_info
(
kdf_info
),
last_error
(
axolotl
::
ErrorCode
::
SUCCESS
)
{
}
void
axolotl
::
Session
::
initialise_as_bob
(
std
::
uint8_t
const
*
shared_secret
,
std
::
size_t
shared_secret_length
,
axolotl
::
Curve25519PublicKey
const
&
their_ratchet_key
)
{
std
::
uint8_t
derived_secrets
[
64
];
axolotl
::
hkdf_sha256
(
shared_secret
,
shared_secret_length
,
NULL
,
0
,
kdf_info
.
root_info
,
kdf_info
.
root_info_length
,
derived_secrets
,
sizeof
(
derived_secrets
)
);
receiver_chains
.
insert
();
std
::
memcpy
(
root_key
,
derived_secrets
,
32
);
std
::
memcpy
(
receiver_chains
[
0
].
chain_key
.
key
,
derived_secrets
+
32
,
32
);
receiver_chains
[
0
].
ratchet_key
=
their_ratchet_key
;
unset
(
derived_secrets
);
}
void
axolotl
::
Session
::
initialise_as_alice
(
std
::
uint8_t
const
*
shared_secret
,
std
::
size_t
shared_secret_length
,
axolotl
::
Curve25519KeyPair
const
&
our_ratchet_key
)
{
std
::
uint8_t
derived_secrets
[
64
];
axolotl
::
hkdf_sha256
(
shared_secret
,
shared_secret_length
,
NULL
,
0
,
kdf_info
.
root_info
,
kdf_info
.
root_info_length
,
derived_secrets
,
sizeof
(
derived_secrets
)
);
sender_chain
.
insert
();
std
::
memcpy
(
root_key
,
derived_secrets
,
32
);
std
::
memcpy
(
sender_chain
[
0
].
chain_key
.
key
,
derived_secrets
+
32
,
32
);
sender_chain
[
0
].
ratchet_key
=
our_ratchet_key
;
unset
(
derived_secrets
);
}
std
::
size_t
axolotl
::
Session
::
encrypt_max_output_length
(
std
::
size_t
axolotl
::
Session
::
encrypt_max_output_length
(
std
::
size_t
plaintext_length
std
::
size_t
plaintext_length
)
{
)
{
std
::
size_t
key_length
=
1
+
varstring_length
(
Curve25519PublicKey
::
Length
);
std
::
size_t
counter
=
0
;
std
::
size_t
counter
=
sender_chain
.
empty
()
?
0
:
sender_chain
[
0
].
index
;
if
(
!
sender_chain
.
empty
())
{
counter
=
sender_chain
[
0
].
chain_key
.
index
;
}
std
::
size_t
padded
=
axolotl
::
aes_encrypt_cbc_length
(
plaintext_length
);
std
::
size_t
padded
=
axolotl
::
aes_encrypt_cbc_length
(
plaintext_length
);
return
axolotl
::
encode_message_length
(
return
axolotl
::
encode_message_length
(
counter
,
KEY_LENGTH
,
padded
,
MAC_LENGTH
counter
,
KEY_LENGTH
,
padded
,
MAC_LENGTH
...
@@ -176,7 +231,7 @@ std::size_t axolotl::Session::encrypt_max_output_length(
...
@@ -176,7 +231,7 @@ std::size_t axolotl::Session::encrypt_max_output_length(
std
::
size_t
axolotl
::
Session
::
encrypt_random_length
()
{
std
::
size_t
axolotl
::
Session
::
encrypt_random_length
()
{
return
sender_chain
.
size
()
?
Curve25519PublicKey
::
Length
:
0
;
return
sender_chain
.
empty
()
?
KEY_LENGTH
:
0
;
}
}
...
@@ -189,29 +244,36 @@ std::size_t axolotl::Session::encrypt(
...
@@ -189,29 +244,36 @@ std::size_t axolotl::Session::encrypt(
last_error
=
axolotl
::
ErrorCode
::
NOT_ENOUGH_RANDOM
;
last_error
=
axolotl
::
ErrorCode
::
NOT_ENOUGH_RANDOM
;
return
std
::
size_t
(
-
1
);
return
std
::
size_t
(
-
1
);
}
}
if
(
max_output_length
<
encrypt_max_output_length
())
{
if
(
max_output_length
<
encrypt_max_output_length
(
plaintext_length
))
{
last_error
=
axolotl
::
ErrorCode
::
OUTPUT_BUFFER_TOO_SMALL
;
last_error
=
axolotl
::
ErrorCode
::
OUTPUT_BUFFER_TOO_SMALL
;
return
std
::
size_t
(
-
1
);
return
std
::
size_t
(
-
1
);
}
}
if
(
sender_chain
.
empty
())
{
if
(
sender_chain
.
empty
())
{
/** create sender chain */
sender_chain
.
insert
();
axolotl
::
generate_key
(
random
,
sender_chain
[
0
].
ratchet_key
);
create_chain_key
(
root_key
,
sender_chain
[
0
].
ratchet_key
,
receiver_chains
[
0
].
ratchet_key
,
kdf_info
,
root_key
,
sender_chain
[
0
].
chain_key
);
}
}
MessageKey
keys
;
MessageKey
keys
;
create_message_keys
(
sender_chain
[
0
].
chain_key
,
kdf_info
,
keys
);
/** create message keys and advance chain */
advance_chain_key
(
sender_chain
[
0
].
chain_key
,
sender_chain
[
0
].
chain_key
);
std
::
size_t
padded
=
axolotl
::
aes_encrypt_cbc_length
(
plaintext_length
);
std
::
size_t
padded
=
axolotl
::
aes_encrypt_cbc_length
(
plaintext_length
);
std
::
size_t
key_length
=
Curve25519PublicKey
::
Length
;
std
::
uint32_t
counter
=
keys
.
index
;
std
::
uint32_t
counter
=
keys
.
index
;
const
Curve25519PublicKey
&
ratchet_key
=
sender_chain
[
0
].
ratchet_key
;
const
Curve25519PublicKey
&
ratchet_key
=
sender_chain
[
0
].
ratchet_key
;
axolotl
::
MessageWriter
writer
(
axolotl
::
encode_message
(
axolotl
::
MessageWriter
writer
(
axolotl
::
encode_message
(
PROTOCOL_VERSION
,
counter
,
key_length
,
padded
,
cipher_tex
t
PROTOCOL_VERSION
,
counter
,
KEY_LENGTH
,
padded
,
outpu
t
));
));
std
::
memcpy
(
writer
.
ratchet_key
,
ratchet_key
.
public_key
,
key_length
);
std
::
memcpy
(
writer
.
ratchet_key
,
ratchet_key
.
public_key
,
KEY_LENGTH
);
axolotl
::
aes_encrypt_cbc
(
axolotl
::
aes_encrypt_cbc
(
keys
.
cipher_key
,
keys
.
iv
,
keys
.
cipher_key
,
keys
.
iv
,
...
@@ -219,19 +281,20 @@ std::size_t axolotl::Session::encrypt(
...
@@ -219,19 +281,20 @@ std::size_t axolotl::Session::encrypt(
writer
.
ciphertext
writer
.
ciphertext
);
);
std
::
uint8_t
mac
[
HMAC_SHA256_OUTPUT_LENGTH
];
std
::
uint8_t
mac
[
axolotl
::
HMAC_SHA256_OUTPUT_LENGTH
];
axolotl
::
hmac_sha256
(
axolotl
::
hmac_sha256
(
keys
.
mac_key
,
sizeof
(
keys
.
mac_key
),
keys
.
mac_key
,
sizeof
(
keys
.
mac_key
),
ciphertex
t
,
writer
.
body_length
,
outpu
t
,
writer
.
body_length
,
mac
mac
);
);
std
::
memcpy
(
writer
.
mac
,
mac
,
MAC_LENGTH
);
std
::
memcpy
(
writer
.
mac
,
mac
,
MAC_LENGTH
);
unset
(
keys
);
return
writer
.
body_length
+
MAC_LENGTH
;
return
writer
.
body_length
+
MAC_LENGTH
;
}
}
std
::
size_t
decrypt_max_plaintext_length
(
std
::
size_t
axolotl
::
Session
::
decrypt_max_plaintext_length
(
std
::
size_t
input_length
std
::
size_t
input_length
)
{
)
{
return
input_length
;
return
input_length
;
...
@@ -256,8 +319,7 @@ std::size_t axolotl::Session::decrypt(
...
@@ -256,8 +319,7 @@ std::size_t axolotl::Session::decrypt(
return
std
::
size_t
(
-
1
);
return
std
::
size_t
(
-
1
);
}
}
if
(
reader
.
body_length
==
0
if
(
reader
.
body_length
==
0
||
reader
.
ratchet_key_length
!=
KEY_LENGTH
)
{
||
reader
.
ratchet_key_length
!=
Curve25519PublicKey
::
Length
)
{
last_error
=
axolotl
::
ErrorCode
::
BAD_MESSAGE_FORMAT
;
last_error
=
axolotl
::
ErrorCode
::
BAD_MESSAGE_FORMAT
;
return
std
::
size_t
(
-
1
);
return
std
::
size_t
(
-
1
);
}
}
...
@@ -265,7 +327,8 @@ std::size_t axolotl::Session::decrypt(
...
@@ -265,7 +327,8 @@ std::size_t axolotl::Session::decrypt(
ReceiverChain
*
chain
=
NULL
;
ReceiverChain
*
chain
=
NULL
;
for
(
axolotl
::
ReceiverChain
&
receiver_chain
:
receiver_chains
)
{
for
(
axolotl
::
ReceiverChain
&
receiver_chain
:
receiver_chains
)
{
if
(
0
==
std
::
memcmp
(
if
(
0
==
std
::
memcmp
(
receiver_chain
.
ratchet_key
,
reader
.
ratchet_key
,
KEY_LENGTH
receiver_chain
.
ratchet_key
.
public_key
,
reader
.
ratchet_key
,
KEY_LENGTH
))
{
))
{
chain
=
&
receiver_chain
;
chain
=
&
receiver_chain
;
break
;
break
;
...
@@ -278,15 +341,16 @@ std::size_t axolotl::Session::decrypt(
...
@@ -278,15 +341,16 @@ std::size_t axolotl::Session::decrypt(
return
std
::
size_t
(
-
1
);
return
std
::
size_t
(
-
1
);
}
}
}
else
{
}
else
{
if
(
chain
->
index
>
reader
.
counter
)
{
if
(
chain
->
chain_key
.
index
>
reader
.
counter
)
{
/* Chain already advanced beyond the key for this message
/* Chain already advanced beyond the key for this message
* Check if the message keys are in the skipped key list. */
* Check if the message keys are in the skipped key list. */
for
(
const
axolotl
::
SkippedMessageKey
&
skipped
for
(
axolotl
::
SkippedMessageKey
&
skipped
:
skipped_message_keys
)
{
:
skipped_message_keys
)
{
if
(
reader
.
counter
==
skipped
.
message_key
.
index
if
(
reader
.
counter
==
skipped
.
message_key
.
index
&&
0
==
std
::
memcmp
(
&&
0
==
std
::
memcmp
(
skipped
.
ratchet_key
,
reader
.
ratchet_key
,
KEY_LENGTH
skipped
.
ratchet_key
.
public_key
,
reader
.
ratchet_key
,
))
{
KEY_LENGTH
)
)
{
/* Found the key for this message. Check the MAC. */
/* Found the key for this message. Check the MAC. */
if
(
!
verify_mac
(
skipped
.
message_key
,
input
,
reader
))
{
if
(
!
verify_mac
(
skipped
.
message_key
,
input
,
reader
))
{
last_error
=
axolotl
::
ErrorCode
::
BAD_MESSAGE_MAC
;
last_error
=
axolotl
::
ErrorCode
::
BAD_MESSAGE_MAC
;
...
@@ -307,6 +371,7 @@ std::size_t axolotl::Session::decrypt(
...
@@ -307,6 +371,7 @@ std::size_t axolotl::Session::decrypt(
/* Remove the key from the skipped keys now that we've
/* Remove the key from the skipped keys now that we've
* decoded the message it corresponds to. */