.Fa "const uint8_t *cipher_text"
.Fa "size_t text_size"
.Fc
+.Ft void
+.Fo crypto_lock_init
+.Fa "crypto_lock_ctx *ctx"
+.Fa "const uint8_t key[32]"
+.Fa "const uint8_t nonce[24]"
+.Fc
+.Ft void
+.Fo crypto_lock_auth
+.Fa crypto_lock_ctx *ctx
+.Fa const uint8_t *ad
+.Fa size_t ad_size
+.Fc
+.Ft void
+.Fo crypto_lock_update
+.Fa crypto_lock_ctx *ctx
+.Fa uint8_t *cipher_text
+.Fa const uint8_t *plain_text
+.Fa size_t text_size
+.Fc
+.Ft void
+.Fo crypto_lock_final
+.Fa crypto_lock_ctx *ctx
+.Fa uint8_t mac[16]
+.Fc
+.Ft void
+.Fo crypto_unlock_update
+.Fa crypto_lock_ctx *ctx
+.Fa uint8_t *plain_text
+.Fa const uint8_t *cipher_text
+.Fa size_t text_size
+.Fc
+.Ft int
+.Fo crypto_unlock_final
+.Fa crypto_lock_ctx *ctx
+.Fa const uint8_t mac[16]
+.Fc
+.F
.Sh DESCRIPTION
Encryption makes your messages unreadable to eavesdroppers.
Authentication ascertain the origin and integrity of the messages you
*/
}
.Ed
+.Sh INCREMENTAL INTERFACE
+Useful for decrypting huge inputs.
+This time, decryption is performed regardless of whether the message
+is corrupted or not.
+This may be relevant if you expect a high rate of corrupted messages.
+.Pp
+Encryption:
+.Bd -literal -offset indent
+/* Prepare the key, nonce, and input */
+
+/* First, initialise the context */
+crypto_lock_ctx ctx;
+crypto_lock_init(&ctx, key, nonce);
+
+/* Second, authenticate the additional data, if any. */
+crypto_lock_auth(&ctx, ad1, ad_size1);
+crypto_lock_auth(&ctx, ad2, ad_size2);
+crypto_lock_auth(&ctx, ad3, ad_size3);
+
+/* Third, encrypt the plain text */
+crypto_lock_update(&ctx, cipher1, plain1, text_size1);
+crypto_lock_update(&ctx, cipher2, plain2, text_size2);
+crypto_lock_update(&ctx, cipher3, plain2, text_size3);
+
+/* Finally, compute the authentication code */
+crypto_lock_final (&ctx, mac);
+.Ed
+.Pp
+Make sure you authenticate the additional data before you begin the
+encryption, or the mac won't be compatible with the direct interface.
+.Pp
+To decrypt the above:
+.Bd -literal -offset indent
+/* First, initialise the context.
+ * Use the key and nonce that were used for encryption.
+ */
+crypto_lock_ctx ctx;
+crypto_lock_init(&ctx, key, nonce);
+
+/* Second, authenticate the additional data, if any. */
+crypto_lock_auth(&ctx, ad1, ad_size1);
+crypto_lock_auth(&ctx, ad2, ad_size2);
+crypto_lock_auth(&ctx, ad3, ad_size3);
+
+/* Third, decrypt the cipher text */
+crypto_unlock_update(&ctx, re_plain1, cipher1, text_size1);
+crypto_unlock_update(&ctx, re_plain2, cipher2, text_size2);
+crypto_unlock_update(&ctx, re_plain3, cipher3, text_size3);
+
+/* Finally, check the authentication code */
+if (crypto_unlock_final(&ctx, mac2)) {
+ /* Message corrupted. */
+} else {
+ /* Decryption went well. */
+}
+.Ed
+.Pp
+To authenticate without decrypting at all:
+.Bd -literal -offset indent
+/* First, initialise the context.
+ * Use the key and nonce that were used for encryption.
+ */
+crypto_lock_ctx ctx;
+crypto_lock_init(&ctx, key, nonce);
+
+/* Second, authenticate the additional data, if any. */
+crypto_lock_auth(&ctx, ad1, ad_size1);
+crypto_lock_auth(&ctx, ad2, ad_size2);
+crypto_lock_auth(&ctx, ad3, ad_size3);
+
+/* Third, authenticate the cipher text */
+crypto_lock_auth(&ctx, re_plain1, cipher1, text_size1);
+crypto_lock_auth(&ctx, re_plain2, cipher2, text_size2);
+crypto_lock_auth(&ctx, re_plain3, cipher3, text_size3);
+
+/* Finally, check the authentication code */
+if (crypto_unlock_final(&ctx, mac2)) {
+ /* Message corrupted. */
+} else {
+ /* Message authentic. */
+}
+.Ed
.Sh SEE ALSO
.Xr crypto_aead_lock 3monocypher ,
.Xr crypto_aead_unlock 3monocypher ,
--- /dev/null
+crypto_lock.3monocypher
\ No newline at end of file
--- /dev/null
+crypto_lock.3monocypher
\ No newline at end of file
--- /dev/null
+crypto_lock.3monocypher
\ No newline at end of file
--- /dev/null
+crypto_lock.3monocypher
\ No newline at end of file
--- /dev/null
+crypto_lock.3monocypher
\ No newline at end of file
--- /dev/null
+crypto_lock.3monocypher
\ No newline at end of file
return crypto_aead_unlock(plain_text, key, nonce, mac, 0, 0,
cipher_text, text_size);
}
+
+void crypto_lock_init(crypto_lock_ctx *ctx, const u8 key[32], const u8 nonce[24])
+{
+ u8 auth_key[32];
+ crypto_chacha20_x_init(&(ctx->chacha), key, nonce);
+ crypto_chacha20_stream(&(ctx->chacha), auth_key, 32);
+ crypto_poly1305_init (&(ctx->poly ), auth_key);
+}
+
+void crypto_lock_auth(crypto_lock_ctx *ctx, const u8 *ad, size_t ad_size)
+{
+ crypto_poly1305_update(&(ctx->poly), ad, ad_size);
+}
+
+void crypto_lock_update(crypto_lock_ctx *ctx, u8 *cipher_text,
+ const u8 *plain_text, size_t text_size)
+{
+ crypto_chacha20_encrypt(&(ctx->chacha), cipher_text, plain_text, text_size);
+ crypto_poly1305_update (&(ctx->poly ), cipher_text, text_size);
+}
+
+void crypto_lock_final(crypto_lock_ctx *ctx, u8 mac[16])
+{
+ crypto_poly1305_final (&(ctx->poly), mac);
+}
+
+void crypto_unlock_update(crypto_lock_ctx *ctx, u8 *plain_text,
+ const u8 *cipher_text, size_t text_size)
+{
+ crypto_poly1305_update (&(ctx->poly ), cipher_text, text_size);
+ crypto_chacha20_encrypt(&(ctx->chacha), plain_text, cipher_text, text_size);
+}
+
+int crypto_unlock_final(crypto_lock_ctx *ctx, const u8 mac[16])
+{
+ u8 real_mac[16];
+ crypto_poly1305_final(&(ctx->poly), real_mac);
+ return crypto_memcmp(real_mac, mac, 16);
+}
const uint8_t mac[16],
const uint8_t *cipher_text, size_t text_size);
+typedef struct {
+ crypto_chacha_ctx chacha;
+ crypto_poly1305_ctx poly;
+} crypto_lock_ctx;
+
+void crypto_lock_init(crypto_lock_ctx *ctx,
+ const uint8_t key[32],
+ const uint8_t nonce[24]);
+
+void crypto_lock_auth(crypto_lock_ctx *ctx,
+ const uint8_t *ad, size_t ad_size);
+
+void crypto_lock_update(crypto_lock_ctx *ctx,
+ uint8_t *cipher_text,
+ const uint8_t *plain_text, size_t text_size);
+
+void crypto_lock_final(crypto_lock_ctx *ctx, uint8_t mac[16]);
+
+void crypto_unlock_update(crypto_lock_ctx *ctx,
+ uint8_t *plain_text,
+ const uint8_t *cipher_text, size_t text_size);
+
+int crypto_unlock_final(crypto_lock_ctx *ctx, const uint8_t mac[16]);
+
#endif // MONOCYPHER_H
return status;
}
+static int p_lock_incremental()
+{
+ int status = 0;
+ FOR (i, 0, 1000) {
+ RANDOM_INPUT(key , 32);
+ RANDOM_INPUT(nonce, 24);
+ RANDOM_INPUT(ad , 128);
+ RANDOM_INPUT(plain, 256);
+ // total sizes
+ size_t ad_size = rand64() % 128;
+ size_t text_size = rand64() % 256;
+ // incremental sizes
+ size_t ad_size1 = ad_size == 0 ? 0 : rand64() % ad_size;
+ size_t text_size1 = text_size == 0 ? 0 : rand64() % text_size;
+ size_t ad_size2 = ad_size - ad_size1;
+ size_t text_size2 = text_size - text_size1;
+ // incremental buffers
+ u8 *ad1 = ad; u8 *ad2 = ad + ad_size1;
+ u8 *plain1 = plain; u8 *plain2 = plain + text_size1;
+
+ u8 mac1[16], cipher1[256];
+ u8 mac2[16], cipher2[256];
+ crypto_aead_lock(mac1, cipher1, key, nonce,
+ ad, ad_size, plain, text_size);
+ crypto_lock_ctx ctx;
+ crypto_lock_init (&ctx, key, nonce);
+ crypto_lock_auth (&ctx, ad1, ad_size1); // just to show ad also have
+ crypto_lock_auth (&ctx, ad2, ad_size2); // an incremental interface
+ crypto_lock_update(&ctx, cipher2 , plain1, text_size1);
+ crypto_lock_update(&ctx, cipher2 + text_size1, plain2, text_size2);
+ crypto_lock_final (&ctx, mac2);
+ status |= crypto_memcmp(mac1 , mac2 , 16 );
+ status |= crypto_memcmp(cipher1, cipher2, text_size);
+
+ // Now test the round trip.
+ u8 re_plain1[256];
+ u8 re_plain2[256];
+ status |= crypto_aead_unlock(re_plain1, key, nonce, mac1,
+ ad, ad_size, cipher1, text_size);
+ crypto_lock_init (&ctx, key, nonce);
+ crypto_lock_auth (&ctx, ad, ad_size);
+ crypto_unlock_update(&ctx, re_plain2, cipher2, text_size);
+ status |= crypto_unlock_final(&ctx, mac2);
+ status |= crypto_memcmp(mac1 , mac2 , 16 );
+ status |= crypto_memcmp(plain, re_plain1, text_size);
+ status |= crypto_memcmp(plain, re_plain2, text_size);
+
+ // Test authentication without decryption
+ crypto_lock_init(&ctx, key, nonce);
+ crypto_lock_auth(&ctx, ad , ad_size );
+ crypto_lock_auth(&ctx, cipher2, text_size);
+ status |= crypto_unlock_final(&ctx, mac2);
+ // The same, except we're supposed to reject forgeries
+ if (text_size > 0) {
+ cipher2[0]++; // forgery attempt
+ crypto_lock_init(&ctx, key, nonce);
+ crypto_lock_auth(&ctx, ad , ad_size );
+ crypto_lock_auth(&ctx, cipher2, text_size);
+ status |= !crypto_unlock_final(&ctx, mac2);
+ }
+ }
+ printf("%s: aead (incremental)\n", status != 0 ? "FAILED" : "OK");
+ return status;
+}
+
int main(void)
{
int status = 0;
status |= p_eddsa();
status |= p_eddsa_overlap();
status |= p_aead();
-
+ status |= p_lock_incremental();
printf("\nConstant time tests");
printf("\n-------------------\n");
status |= test_cmp();
- printf("\n");
+ printf("\n%s\n\n", status != 0 ? "SOME TESTS FAILED" : "All tests OK!");
return status;
}