Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137789019
D28757.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D28757.diff
View Options
diff --git a/share/man/man4/ossl.4 b/share/man/man4/ossl.4
--- a/share/man/man4/ossl.4
+++ b/share/man/man4/ossl.4
@@ -76,6 +76,8 @@
.It
ChaCha20
.It
+ChaCha20-Poly1305 (RFC 8439)
+.It
Poly1305
.It
SHA1
diff --git a/sys/crypto/openssl/ossl.h b/sys/crypto/openssl/ossl.h
--- a/sys/crypto/openssl/ossl.h
+++ b/sys/crypto/openssl/ossl.h
@@ -39,6 +39,10 @@
int ossl_chacha20(struct cryptop *crp,
const struct crypto_session_params *csp);
+int ossl_chacha20_poly1305_decrypt(struct cryptop *crp,
+ const struct crypto_session_params *csp);
+int ossl_chacha20_poly1305_encrypt(struct cryptop *crp,
+ const struct crypto_session_params *csp);
void ossl_cpuid(void);
/* Needs to be big enough to hold any hash context. */
diff --git a/sys/crypto/openssl/ossl.c b/sys/crypto/openssl/ossl.c
--- a/sys/crypto/openssl/ossl.c
+++ b/sys/crypto/openssl/ossl.c
@@ -165,6 +165,14 @@
return (EINVAL);
}
break;
+ case CSP_MODE_AEAD:
+ switch (csp->csp_cipher_alg) {
+ case CRYPTO_CHACHA20_POLY1305:
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
default:
return (EINVAL);
}
@@ -314,6 +322,12 @@
case CSP_MODE_CIPHER:
error = ossl_chacha20(crp, csp);
break;
+ case CSP_MODE_AEAD:
+ if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
+ error = ossl_chacha20_poly1305_encrypt(crp, csp);
+ else
+ error = ossl_chacha20_poly1305_decrypt(crp, csp);
+ break;
default:
__assert_unreachable();
}
diff --git a/sys/crypto/openssl/ossl_chacha20.c b/sys/crypto/openssl/ossl_chacha20.c
--- a/sys/crypto/openssl/ossl_chacha20.c
+++ b/sys/crypto/openssl/ossl_chacha20.c
@@ -37,6 +37,7 @@
#include <crypto/openssl/ossl.h>
#include <crypto/openssl/ossl_chacha.h>
+#include <crypto/openssl/ossl_poly1305.h>
int
ossl_chacha20(struct cryptop *crp, const struct crypto_session_params *csp)
@@ -139,3 +140,308 @@
explicit_bzero(key, sizeof(key));
return (0);
}
+
+int
+ossl_chacha20_poly1305_encrypt(struct cryptop *crp,
+ const struct crypto_session_params *csp)
+{
+ _Alignas(8) unsigned int key[CHACHA_KEY_SIZE / 4];
+ unsigned int counter[CHACHA_CTR_SIZE / 4];
+ _Alignas(8) unsigned char block[CHACHA_BLK_SIZE];
+ unsigned char tag[POLY1305_HASH_LEN];
+ POLY1305 auth_ctx;
+ struct crypto_buffer_cursor cc_in, cc_out;
+ const unsigned char *in, *inseg, *cipher_key;
+ unsigned char *out, *outseg;
+ size_t resid, todo, inlen, outlen;
+ uint32_t next_counter;
+ u_int i;
+
+ if (crp->crp_cipher_key != NULL)
+ cipher_key = crp->crp_cipher_key;
+ else
+ cipher_key = csp->csp_cipher_key;
+ for (i = 0; i < nitems(key); i++)
+ key[i] = CHACHA_U8TOU32(cipher_key + i * 4);
+
+ crypto_read_iv(crp, counter + 1);
+ for (i = 1; i < nitems(counter); i++)
+ counter[i] = le32toh(counter[i]);
+
+ /* Block 0 is used to generate the poly1305 key. */
+ counter[0] = 0;
+
+ memset(block, 0, sizeof(block));
+ ChaCha20_ctr32(block, block, sizeof(block), key, counter);
+ Poly1305_Init(&auth_ctx, block);
+
+ /* MAC the AAD. */
+ if (crp->crp_aad != NULL)
+ Poly1305_Update(&auth_ctx, crp->crp_aad, crp->crp_aad_length);
+ else
+ crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
+ ossl_poly1305_update, &auth_ctx);
+ if (crp->crp_aad_length % 16 != 0) {
+ /* padding1 */
+ memset(block, 0, 16);
+ Poly1305_Update(&auth_ctx, block,
+ 16 - crp->crp_aad_length % 16);
+ }
+
+ /* Encryption starts with block 1. */
+ counter[0] = 1;
+
+ /* Do encryption with MAC */
+ resid = crp->crp_payload_length;
+ crypto_cursor_init(&cc_in, &crp->crp_buf);
+ crypto_cursor_advance(&cc_in, crp->crp_payload_start);
+ inseg = crypto_cursor_segbase(&cc_in);
+ inlen = crypto_cursor_seglen(&cc_in);
+ if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
+ crypto_cursor_init(&cc_out, &crp->crp_obuf);
+ crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
+ } else
+ cc_out = cc_in;
+ outseg = crypto_cursor_segbase(&cc_out);
+ outlen = crypto_cursor_seglen(&cc_out);
+ while (resid >= CHACHA_BLK_SIZE) {
+ if (inlen < CHACHA_BLK_SIZE) {
+ crypto_cursor_copydata(&cc_in, CHACHA_BLK_SIZE, block);
+ in = block;
+ inlen = CHACHA_BLK_SIZE;
+ } else
+ in = inseg;
+ if (outlen < CHACHA_BLK_SIZE) {
+ out = block;
+ outlen = CHACHA_BLK_SIZE;
+ } else
+ out = outseg;
+
+ /* Figure out how many blocks we can encrypt/decrypt at once. */
+ todo = rounddown(MIN(inlen, outlen), CHACHA_BLK_SIZE);
+
+#ifdef __LP64__
+ /* ChaCha20_ctr32() assumes length is <= 4GB. */
+ todo = (uint32_t)todo;
+#endif
+
+ /* Truncate if the 32-bit counter would roll over. */
+ next_counter = counter[0] + todo / CHACHA_BLK_SIZE;
+ if (next_counter < counter[0]) {
+ todo -= next_counter * CHACHA_BLK_SIZE;
+ next_counter = 0;
+ }
+
+ ChaCha20_ctr32(out, in, todo, key, counter);
+ Poly1305_Update(&auth_ctx, out, todo);
+
+ counter[0] = next_counter;
+ if (counter[0] == 0)
+ counter[1]++;
+
+ if (out == block) {
+ crypto_cursor_copyback(&cc_out, CHACHA_BLK_SIZE, block);
+ outseg = crypto_cursor_segbase(&cc_out);
+ outlen = crypto_cursor_seglen(&cc_out);
+ } else {
+ crypto_cursor_advance(&cc_out, todo);
+ outseg += todo;
+ outlen -= todo;
+ }
+ if (in == block) {
+ inseg = crypto_cursor_segbase(&cc_in);
+ inlen = crypto_cursor_seglen(&cc_in);
+ } else {
+ crypto_cursor_advance(&cc_in, todo);
+ inseg += todo;
+ inlen -= todo;
+ }
+ resid -= todo;
+ }
+
+ if (resid > 0) {
+ memset(block, 0, sizeof(block));
+ crypto_cursor_copydata(&cc_in, resid, block);
+ ChaCha20_ctr32(block, block, CHACHA_BLK_SIZE, key, counter);
+ crypto_cursor_copyback(&cc_out, resid, block);
+
+ /* padding2 */
+ todo = roundup2(resid, 16);
+ memset(block + resid, 0, todo - resid);
+ Poly1305_Update(&auth_ctx, block, todo);
+ }
+
+ /* lengths */
+ le64enc(block, crp->crp_aad_length);
+ le64enc(block + 8, crp->crp_payload_length);
+ Poly1305_Update(&auth_ctx, block, sizeof(uint64_t) * 2);
+
+ Poly1305_Final(&auth_ctx, tag);
+ crypto_copyback(crp, crp->crp_digest_start, csp->csp_auth_mlen == 0 ?
+ POLY1305_HASH_LEN : csp->csp_auth_mlen, tag);
+
+ explicit_bzero(&auth_ctx, sizeof(auth_ctx));
+ explicit_bzero(tag, sizeof(tag));
+ explicit_bzero(block, sizeof(block));
+ explicit_bzero(counter, sizeof(counter));
+ explicit_bzero(key, sizeof(key));
+ return (0);
+}
+
+
+int
+ossl_chacha20_poly1305_decrypt(struct cryptop *crp,
+ const struct crypto_session_params *csp)
+{
+ _Alignas(8) unsigned int key[CHACHA_KEY_SIZE / 4];
+ unsigned int counter[CHACHA_CTR_SIZE / 4];
+ _Alignas(8) unsigned char block[CHACHA_BLK_SIZE];
+ unsigned char tag[POLY1305_HASH_LEN], tag2[POLY1305_HASH_LEN];
+ struct poly1305_context auth_ctx;
+ struct crypto_buffer_cursor cc_in, cc_out;
+ const unsigned char *in, *inseg, *cipher_key;
+ unsigned char *out, *outseg;
+ size_t resid, todo, inlen, outlen;
+ uint32_t next_counter;
+ int error;
+ u_int i, mlen;
+
+ if (crp->crp_cipher_key != NULL)
+ cipher_key = crp->crp_cipher_key;
+ else
+ cipher_key = csp->csp_cipher_key;
+ for (i = 0; i < nitems(key); i++)
+ key[i] = CHACHA_U8TOU32(cipher_key + i * 4);
+
+ crypto_read_iv(crp, counter + 1);
+ for (i = 1; i < nitems(counter); i++)
+ counter[i] = le32toh(counter[i]);
+
+ /* Block 0 is used to generate the poly1305 key. */
+ counter[0] = 0;
+
+ memset(block, 0, sizeof(block));
+ ChaCha20_ctr32(block, block, sizeof(block), key, counter);
+ Poly1305_Init(&auth_ctx, block);
+
+ /* MAC the AAD. */
+ if (crp->crp_aad != NULL)
+ Poly1305_Update(&auth_ctx, crp->crp_aad, crp->crp_aad_length);
+ else
+ crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
+ ossl_poly1305_update, &auth_ctx);
+ if (crp->crp_aad_length % 16 != 0) {
+ /* padding1 */
+ memset(block, 0, 16);
+ Poly1305_Update(&auth_ctx, block,
+ 16 - crp->crp_aad_length % 16);
+ }
+
+ /* Mac the ciphertext. */
+ crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length,
+ ossl_poly1305_update, &auth_ctx);
+ if (crp->crp_payload_length % 16 != 0) {
+ /* padding2 */
+ memset(block, 0, 16);
+ Poly1305_Update(&auth_ctx, block,
+ 16 - crp->crp_payload_length % 16);
+ }
+
+ /* lengths */
+ le64enc(block, crp->crp_aad_length);
+ le64enc(block + 8, crp->crp_payload_length);
+ Poly1305_Update(&auth_ctx, block, sizeof(uint64_t) * 2);
+
+ Poly1305_Final(&auth_ctx, tag);
+ mlen = csp->csp_auth_mlen == 0 ? POLY1305_HASH_LEN : csp->csp_auth_mlen;
+ crypto_copydata(crp, crp->crp_digest_start, mlen, tag2);
+ if (timingsafe_bcmp(tag, tag2, mlen) != 0) {
+ error = EBADMSG;
+ goto out;
+ }
+
+ /* Decryption starts with block 1. */
+ counter[0] = 1;
+
+ resid = crp->crp_payload_length;
+ crypto_cursor_init(&cc_in, &crp->crp_buf);
+ crypto_cursor_advance(&cc_in, crp->crp_payload_start);
+ inseg = crypto_cursor_segbase(&cc_in);
+ inlen = crypto_cursor_seglen(&cc_in);
+ if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
+ crypto_cursor_init(&cc_out, &crp->crp_obuf);
+ crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
+ } else
+ cc_out = cc_in;
+ outseg = crypto_cursor_segbase(&cc_out);
+ outlen = crypto_cursor_seglen(&cc_out);
+ while (resid >= CHACHA_BLK_SIZE) {
+ if (inlen < CHACHA_BLK_SIZE) {
+ crypto_cursor_copydata(&cc_in, CHACHA_BLK_SIZE, block);
+ in = block;
+ inlen = CHACHA_BLK_SIZE;
+ } else
+ in = inseg;
+ if (outlen < CHACHA_BLK_SIZE) {
+ out = block;
+ outlen = CHACHA_BLK_SIZE;
+ } else
+ out = outseg;
+
+ /* Figure out how many blocks we can encrypt/decrypt at once. */
+ todo = rounddown(MIN(inlen, outlen), CHACHA_BLK_SIZE);
+
+#ifdef __LP64__
+ /* ChaCha20_ctr32() assumes length is <= 4GB. */
+ todo = (uint32_t)todo;
+#endif
+
+ /* Truncate if the 32-bit counter would roll over. */
+ next_counter = counter[0] + todo / CHACHA_BLK_SIZE;
+ if (next_counter < counter[0]) {
+ todo -= next_counter * CHACHA_BLK_SIZE;
+ next_counter = 0;
+ }
+
+ ChaCha20_ctr32(out, in, todo, key, counter);
+
+ counter[0] = next_counter;
+ if (counter[0] == 0)
+ counter[1]++;
+
+ if (out == block) {
+ crypto_cursor_copyback(&cc_out, CHACHA_BLK_SIZE, block);
+ outseg = crypto_cursor_segbase(&cc_out);
+ outlen = crypto_cursor_seglen(&cc_out);
+ } else {
+ crypto_cursor_advance(&cc_out, todo);
+ outseg += todo;
+ outlen -= todo;
+ }
+ if (in == block) {
+ inseg = crypto_cursor_segbase(&cc_in);
+ inlen = crypto_cursor_seglen(&cc_in);
+ } else {
+ crypto_cursor_advance(&cc_in, todo);
+ inseg += todo;
+ inlen -= todo;
+ }
+ resid -= todo;
+ }
+
+ if (resid > 0) {
+ memset(block, 0, sizeof(block));
+ crypto_cursor_copydata(&cc_in, resid, block);
+ ChaCha20_ctr32(block, block, CHACHA_BLK_SIZE, key, counter);
+ crypto_cursor_copyback(&cc_out, resid, block);
+ }
+
+ error = 0;
+out:
+ explicit_bzero(&auth_ctx, sizeof(auth_ctx));
+ explicit_bzero(tag, sizeof(tag));
+ explicit_bzero(block, sizeof(block));
+ explicit_bzero(counter, sizeof(counter));
+ explicit_bzero(key, sizeof(key));
+ return (error);
+}
diff --git a/sys/crypto/openssl/ossl_poly1305.h b/sys/crypto/openssl/ossl_poly1305.h
--- a/sys/crypto/openssl/ossl_poly1305.h
+++ b/sys/crypto/openssl/ossl_poly1305.h
@@ -33,3 +33,8 @@
poly1305_emit_f emit;
} func;
};
+
+int ossl_poly1305_update(void *vctx, const void *buf, u_int len);
+void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32]);
+void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len);
+void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16]);
diff --git a/sys/crypto/openssl/ossl_poly1305.c b/sys/crypto/openssl/ossl_poly1305.c
--- a/sys/crypto/openssl/ossl_poly1305.c
+++ b/sys/crypto/openssl/ossl_poly1305.c
@@ -46,7 +46,7 @@
void poly1305_emit(void *ctx, unsigned char mac[16],
const unsigned int nonce[4]);
-static void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32])
+void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32])
{
ctx->nonce[0] = U8TOU32(&key[16]);
ctx->nonce[1] = U8TOU32(&key[20]);
@@ -77,7 +77,7 @@
# define poly1305_emit (*poly1305_emit_p)
#endif
-static void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len)
+void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len)
{
#ifdef POLY1305_ASM
/*
@@ -119,7 +119,7 @@
ctx->num = rem;
}
-static void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16])
+void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16])
{
#ifdef POLY1305_ASM
poly1305_blocks_f poly1305_blocks_p = ctx->func.blocks;
@@ -152,7 +152,7 @@
Poly1305_Init(vctx, key);
}
-static int
+int
ossl_poly1305_update(void *vctx, const void *buf, u_int len)
{
Poly1305_Update(vctx, buf, len);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 26, 9:04 PM (14 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26226558
Default Alt Text
D28757.diff (12 KB)
Attached To
Mode
D28757: ossl: Add support for the ChaCha20 + Poly1305 AEAD cipher from RFC 8439
Attached
Detach File
Event Timeline
Log In to Comment