Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
R
RIOT
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
cm-projects
RIOT
Commits
1990e162
Unverified
Commit
1990e162
authored
6 years ago
by
Koen Zandberg
Browse files
Options
Downloads
Patches
Plain Diff
crypto: Add chacha20poly1305 AEAD algorithm
parent
90db0bf2
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
sys/crypto/chacha20poly1305.c
+177
-0
177 additions, 0 deletions
sys/crypto/chacha20poly1305.c
sys/include/crypto/chacha20poly1305.h
+104
-0
104 additions, 0 deletions
sys/include/crypto/chacha20poly1305.h
with
281 additions
and
0 deletions
sys/crypto/chacha20poly1305.c
0 → 100644
+
177
−
0
View file @
1990e162
/*
* Copyright (C) 2008 D. J. Bernstein (dedicated to the public domain)
* Copyright (C) 2015 René Kijewski <rene.kijewski@fu-berlin.de>
* Copyright (C) 2018 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_crypto_chacha20poly1305
* @{
* @file
* @brief Implementation of the chacha20poly1305 aead cipher
*
* @author Koen Zandberg <koen@bergzand.net>
* @see https://tools.ietf.org/html/rfc8439
* @}
*/
#include
<stdlib.h>
#include
<stdint.h>
#include
<string.h>
#include
"crypto/helper.h"
#include
"crypto/chacha20poly1305.h"
#include
"crypto/poly1305.h"
/* Missing operations to convert numbers to little endian prevents this from
* working on big endian systems */
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
# error "This code is implementented in a way that it will only work for little-endian systems!"
#endif
/* Nothing to hide here, Literally "expand 32-byte k" */
static
const
uint32_t
constant
[]
=
{
0x61707865
,
0x3320646e
,
0x79622d32
,
0x6b206574
};
/* Padding to add to the poly1305 authentication tag */
static
const
uint8_t
padding
[
15
]
=
{
0
};
static
uint32_t
u8to32
(
const
uint8_t
*
p
)
{
return
((
uint32_t
)
p
[
0
]
|
((
uint32_t
)
p
[
1
]
<<
8
)
|
((
uint32_t
)
p
[
2
]
<<
16
)
|
((
uint32_t
)
p
[
3
]
<<
24
));
}
/* Single round */
void
_r
(
uint32_t
*
a
,
uint32_t
*
b
,
uint32_t
*
d
,
unsigned
c
)
{
*
a
+=
*
b
;
uint32_t
tmp
=
*
a
^
*
d
;
*
d
=
(
tmp
<<
c
)
|
(
tmp
>>
(
32
-
c
));
}
void
_add_initial
(
chacha20poly1305_ctx_t
*
ctx
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
,
uint32_t
blk
)
{
for
(
unsigned
i
=
0
;
i
<
4
;
i
++
)
{
ctx
->
state
[
i
]
+=
constant
[
i
];
}
for
(
unsigned
i
=
0
;
i
<
8
;
i
++
)
{
ctx
->
state
[
i
+
4
]
+=
u8to32
(
key
+
4
*
i
);
}
ctx
->
state
[
12
]
+=
u8to32
((
uint8_t
*
)
&
blk
);
ctx
->
state
[
13
]
+=
u8to32
(
nonce
);
ctx
->
state
[
14
]
+=
u8to32
(
nonce
+
4
);
ctx
->
state
[
15
]
+=
u8to32
(
nonce
+
8
);
}
void
_keystream
(
chacha20poly1305_ctx_t
*
ctx
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
,
uint32_t
blk
)
{
/* Initialize block state */
memset
(
ctx
->
state
,
0
,
sizeof
(
ctx
->
state
));
_add_initial
(
ctx
,
key
,
nonce
,
blk
);
/* perform rounds */
for
(
unsigned
i
=
0
;
i
<
80
;
++
i
)
{
uint32_t
*
a
=
&
ctx
->
state
[((
i
)
&
3
)
];
uint32_t
*
b
=
&
ctx
->
state
[((
i
+
((
i
&
4
)
?
1
:
0
))
&
3
)
+
(
4
*
1
)];
uint32_t
*
c
=
&
ctx
->
state
[((
i
+
((
i
&
4
)
?
2
:
0
))
&
3
)
+
(
4
*
2
)];
uint32_t
*
d
=
&
ctx
->
state
[((
i
+
((
i
&
4
)
?
3
:
0
))
&
3
)
+
(
4
*
3
)];
_r
(
a
,
b
,
d
,
16
);
_r
(
c
,
d
,
b
,
12
);
_r
(
a
,
b
,
d
,
8
);
_r
(
c
,
d
,
b
,
7
);
}
/* add initial state */
_add_initial
(
ctx
,
key
,
nonce
,
blk
);
}
void
_xcrypt
(
chacha20poly1305_ctx_t
*
ctx
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
,
const
uint8_t
*
in
,
uint8_t
*
out
,
size_t
len
)
{
/* Number of full 64 byte blocks */
const
size_t
num_blocks
=
len
>>
6
;
size_t
pos
=
0
;
/* xcrypt full blocks */
for
(
size_t
i
=
0
;
i
<
num_blocks
;
i
++
,
pos
+=
64
)
{
_keystream
(
ctx
,
key
,
nonce
,
i
+
1
);
for
(
size_t
j
=
0
;
j
<
64
;
j
++
)
{
out
[
pos
+
j
]
=
in
[
pos
+
j
]
^
((
uint8_t
*
)
ctx
->
state
)[
j
];
}
}
/* xcrypt remaining bytes */
if
(
len
-
pos
)
{
_keystream
(
ctx
,
key
,
nonce
,
num_blocks
+
1
);
for
(
size_t
j
=
0
;
j
<
len
-
pos
;
j
++
)
{
out
[
pos
+
j
]
=
in
[
pos
+
j
]
^
((
uint8_t
*
)
ctx
->
state
)[
j
];
}
}
}
void
_poly1305_padded
(
poly1305_ctx_t
*
pctx
,
const
uint8_t
*
data
,
size_t
len
)
{
poly1305_update
(
pctx
,
data
,
len
);
const
size_t
padlen
=
(
16
-
len
)
&
0xF
;
poly1305_update
(
pctx
,
padding
,
padlen
);
}
/* Generate a poly1305 tag */
void
_poly1305_gentag
(
uint8_t
*
mac
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
,
const
uint8_t
*
cipher
,
size_t
cipherlen
,
const
uint8_t
*
aad
,
size_t
aadlen
)
{
chacha20poly1305_ctx_t
ctx
;
/* generate one time key */
_keystream
(
&
ctx
,
key
,
nonce
,
0
);
poly1305_init
(
&
ctx
.
poly
,
(
uint8_t
*
)
ctx
.
state
);
/* Add aad */
_poly1305_padded
(
&
ctx
.
poly
,
aad
,
aadlen
);
/* Add ciphertext */
_poly1305_padded
(
&
ctx
.
poly
,
cipher
,
cipherlen
);
/* Add aad length */
const
uint64_t
lengths
[
2
]
=
{
aadlen
,
cipherlen
};
poly1305_update
(
&
ctx
.
poly
,
(
uint8_t
*
)
lengths
,
sizeof
(
lengths
));
poly1305_finish
(
&
ctx
.
poly
,
mac
);
crypto_secure_wipe
(
&
ctx
,
sizeof
(
ctx
));
}
void
chacha20poly1305_encrypt
(
uint8_t
*
cipher
,
const
uint8_t
*
msg
,
size_t
msglen
,
const
uint8_t
*
aad
,
size_t
aadlen
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
)
{
chacha20poly1305_ctx_t
ctx
;
_xcrypt
(
&
ctx
,
key
,
nonce
,
msg
,
cipher
,
msglen
);
crypto_secure_wipe
(
&
ctx
,
sizeof
(
ctx
));
/* Generate tag */
_poly1305_gentag
(
&
cipher
[
msglen
],
key
,
nonce
,
cipher
,
msglen
,
aad
,
aadlen
);
/* Wipe structures */
}
int
chacha20poly1305_decrypt
(
const
uint8_t
*
cipher
,
size_t
cipherlen
,
uint8_t
*
msg
,
size_t
*
msglen
,
const
uint8_t
*
aad
,
size_t
aadlen
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
)
{
*
msglen
=
cipherlen
-
CHACHA20POLY1305_TAG_BYTES
;
uint8_t
mac
[
16
];
_poly1305_gentag
(
mac
,
key
,
nonce
,
cipher
,
cipherlen
-
CHACHA20POLY1305_TAG_BYTES
,
aad
,
aadlen
);
if
(
crypto_equals
(
cipher
+*
msglen
,
mac
,
CHACHA20POLY1305_TAG_BYTES
)
==
0
)
{
return
0
;
}
chacha20poly1305_ctx_t
ctx
;
/* Number of full blocks */
_xcrypt
(
&
ctx
,
key
,
nonce
,
cipher
,
msg
,
*
msglen
);
return
1
;
}
This diff is collapsed.
Click to expand it.
sys/include/crypto/chacha20poly1305.h
0 → 100644
+
104
−
0
View file @
1990e162
/*
* Copyright (C) 2018 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup sys_crypto_chacha20poly1305 chacha20poly1305 AEAD cipher
* @ingroup sys_crypto
* @brief Provides RFC 8439 style chacha20poly1305
*
* This module provides the chacha20poly1305 AEAD symmetric cipher following
* [rfc 8439](https://tools.ietf.org/html/rfc8439).
*
* Nonces must be unique per message for a single key. They are allowed to be
* predictable, e.g. a message counter and are allowed to be visible during
* transmission.
* @{
*
* @file
* @brief Chacha20poly1305 functions
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef CRYPTO_CHACHA20POLY1305_H
#define CRYPTO_CHACHA20POLY1305_H
#include
"crypto/poly1305.h"
#ifdef __cplusplus
extern
"C"
{
#endif
#define CHACHA20POLY1305_KEY_BYTES (32U)
/**< Key length in bytes */
#define CHACHA20POLY1305_NONCE_BYTES (12U)
/**< Nonce length in bytes */
#define CHACHA20POLY1305_TAG_BYTES (16U)
/**< Tag length in bytes */
/**
* @brief Chacha20poly1305 state struct
*/
typedef
union
{
/* We need both the state matrix and the poly1305 state, but nearly not at
* the same time. This works as long as the first 8 members of state
* overlap fully or completely not with the first and second key parts
* from the @ref poly1305_ctx_t struct */
uint32_t
state
[
16
];
/**< The current state of the key stream. */
poly1305_ctx_t
poly
;
/**< Poly1305 state for the MAC */
}
chacha20poly1305_ctx_t
;
/**
* @brief Encrypt a plaintext to ciphertext and append a tag to protect the
* ciphertext and additional data.
*
* It is allowed to have cipher == msg as long
* as there is @ref CHACHA20POLY1305_TAG_BYTES space left to hold the
* authentication tag
*
*
* @param[out] cipher resulting ciphertext, is CHACHA20POLY1305_TAG_BYTES
* longer than the message length
* @param[in] msg message to encrypt
* @param[in] msglen length in bytes of the message
* @param[in] aad additional authenticated data to protect
* @param[in] aadlen length of the additional authenticated data
* @param[in] key key to encrypt with, must be
* CHACHA20POLY1305_KEY_BYTES long
* @param[in] nonce Nonce to use. Must be CHACHA20POLY1305_NONCE_BYTES
* long
*/
void
chacha20poly1305_encrypt
(
uint8_t
*
cipher
,
const
uint8_t
*
msg
,
size_t
msglen
,
const
uint8_t
*
aad
,
size_t
aadlen
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
);
/**
* @brief Verify the tag and decrypt a ciphertext to plaintext.
*
* It is allowed to have cipher == msg
*
* @param[in] cipher resulting ciphertext, is CHACHA20POLY1305_TAG_BYTES
* longer than the message length
* @param[in] cipherlen length of the ciphertext
* @param[out] msg message to encrypt
* @param[in] msglen resulting length in bytes of the message
* @param[in] aad additional authenticated data to verify
* @param[in] aadlen length of the additional authenticated data
* @param[in] key key to decrypt with, must be
* CHACHA20POLY1305_KEY_BYTES long
* @param[in] nonce Nonce to use. Must be CHACHA20POLY1305_NONCE_BYTES
* long
*/
int
chacha20poly1305_decrypt
(
const
uint8_t
*
cipher
,
size_t
cipherlen
,
uint8_t
*
msg
,
size_t
*
msglen
,
const
uint8_t
*
aad
,
size_t
aadlen
,
const
uint8_t
*
key
,
const
uint8_t
*
nonce
);
#ifdef __cplusplus
}
#endif
#endif
/* CRYPTO_CHACHA20POLY1305_H */
/** @} */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment