#include <crypto_box.h>
#include <randombytes.h>
#include <string.h>
#include <stdio.h>

#define SPACE 10001
#define ALIGNMENT 16
#define ZEROBYTES crypto_box_ZEROBYTES

static unsigned char alicesk[ALIGNMENT + crypto_box_SECRETKEYBYTES] __attribute__((aligned(ALIGNMENT)));
static unsigned char alicepk[ALIGNMENT + crypto_box_PUBLICKEYBYTES] __attribute__((aligned(ALIGNMENT)));
static unsigned char bobsk[ALIGNMENT + crypto_box_SECRETKEYBYTES] __attribute__((aligned(ALIGNMENT)));
static unsigned char bobpk[ALIGNMENT + crypto_box_PUBLICKEYBYTES] __attribute__((aligned(ALIGNMENT)));
static unsigned char n[ALIGNMENT + crypto_box_NONCEBYTES] __attribute__((aligned(ALIGNMENT)));
static unsigned char c[ALIGNMENT + SPACE] __attribute__((aligned(ALIGNMENT)));
static unsigned char m[ALIGNMENT + SPACE] __attribute__((aligned(ALIGNMENT)));
static unsigned char m2[ALIGNMENT + SPACE] __attribute__((aligned(ALIGNMENT)));
static unsigned long long mlen;

int main(void) {

    long long i = 0, j;

    /* test box */
    printf("test box ... begin\n");
    for (mlen = SPACE - SPACE/150; mlen < SPACE && mlen + ZEROBYTES < SPACE; ++mlen) {
#if 0
        printf("crypto_box test, offset = %lld ... begin\n", i); fflush(stdout);
#endif
        i = (i + 1) % ALIGNMENT;
        crypto_box_keypair(alicepk + i, alicesk + i);
        crypto_box_keypair(bobpk + i, bobsk + i);
        randombytes(n + i, crypto_box_NONCEBYTES);
        memset(m, 0, ZEROBYTES + i);
        randombytes(m + ZEROBYTES + i, mlen);
        crypto_box(c + i, m + i, mlen + ZEROBYTES, n + i, bobpk + i, alicesk + i);
        if (crypto_box_open(m2 + i, c + i, mlen + ZEROBYTES, n + i, alicepk + i, bobsk + i) == 0) {
            for (j = 0; j < mlen + ZEROBYTES; ++j) {
                if (m2[j + i] != m[j + i]) {
                    fprintf(stderr, "crypto_box test, offset = %lld ... bad decryption\n", i); fflush(stderr);
                    return 1;
                }
            }
        }
        else {
            fprintf(stderr, "crypto_box test, offset = %lld ... ciphertext fails verification\n", i); fflush(stderr);
            return 1;
        }
        printf("crypto_box test, offset = %lld, mlen = %llu ... OK\n", i, mlen); fflush(stdout);
    }

    return 0;
}
