Beispiel #1
0
void crypto_encryptAndSeal(const uint8_t* key, uint8_t* nonce, uint8_t* plain, uint16_t length, uint8_t* output_buf, uint8_t* output_mac)
{
  uint8_t polykey[sizeof(zeros64)];
  crypto_stream_chacha20_xor(polykey, zeros64, sizeof(zeros64), nonce, key, 0);

  uint8_t padding = (16 - length % 16) % 16;
  uint8_t message[length + padding + 16];

  crypto_stream_chacha20_xor(message, plain, length, nonce, key, 1);
  memset(message + length, 0, padding + 16);
  message[length + padding + 8] = (uint8_t)length;
  message[length + padding + 9] = (uint8_t)(length >> 8);

  crypto_onetimeauth_poly1305(output_mac, message, sizeof(message), polykey);

  memcpy(output_buf, message, length);
}
Beispiel #2
0
int dfcrypt_decrypt(
    const dfcrypt_state_t *state,
    const unsigned char *ctxt,
    size_t ctxt_len_bytes,
    const unsigned char *message_number,
    unsigned char *ptxt_out
)
{
    const unsigned char *salt = ctxt;
    const unsigned char *nonce = ctxt + DFCRYPT_INTERNAL_SALT_BYTES;
    const unsigned char *encrypted = nonce + crypto_stream_chacha20_NONCEBYTES;
    const unsigned char *ciphertext_mac = ctxt + ctxt_len_bytes - DFCRYPT_INTERNAL_MAC_BYTES;

    unsigned char keys[DFCRYPT_INTERNAL_AKEY_BYTES + DFCRYPT_INTERNAL_EKEY_BYTES];
    const unsigned char *akey = keys;
    const unsigned char *ekey = keys + DFCRYPT_INTERNAL_AKEY_BYTES;

    unsigned char computed_mac[DFCRYPT_INTERNAL_MAC_BYTES];

    /* Derive the authentication and encryption keys. */
    assert(sizeof(keys) == 64);
    crypto_generichash_blake2b_salt_personal(
        keys,                   /* output */
        sizeof(keys),           /* output length */
        state->appseed,         /* input */
        state->appseed_length,  /* input length */
        state->key,             /* key */
        DFCRYPT_KEY_BYTES,      /* key length */
        salt,                   /* salt */
        message_number          /* personalization (can be NULL) */
    );

    /* Re-compute the MAC. */
    crypto_generichash_blake2b(
        computed_mac,                                   /* output */
        DFCRYPT_INTERNAL_MAC_BYTES,                     /* output length */
        ctxt,                                           /* input */
        ctxt_len_bytes - DFCRYPT_INTERNAL_MAC_BYTES,    /* input length */
        akey,                                           /* key */
        DFCRYPT_INTERNAL_AKEY_BYTES                     /* key length */
    );

    /* Check the MAC. */
    if (sodium_memcmp(computed_mac, ciphertext_mac, DFCRYPT_INTERNAL_MAC_BYTES) != 0) {
        return -1;
    }

    /* Decrypt the plaintext. */
    crypto_stream_chacha20_xor(
        ptxt_out,                                   /* output */
        encrypted,                                  /* input */
        ctxt_len_bytes - DFCRYPT_CIPHERTEXT_GROWTH, /* input length */
        nonce,                                      /* nonce */
        ekey                                        /* key */
    );

    return 0;
}
Beispiel #3
0
void dfcrypt_encrypt(
    const dfcrypt_state_t *state,
    const unsigned char *ptxt,
    size_t ptxt_len_bytes,
    const unsigned char *message_number,
    unsigned char *ctxt_out
)
{
    unsigned char *salt = ctxt_out;
    unsigned char *nonce = ctxt_out + DFCRYPT_INTERNAL_SALT_BYTES;
    unsigned char *encrypted = nonce + crypto_stream_chacha20_NONCEBYTES;
    unsigned char *mac = encrypted + ptxt_len_bytes;

    unsigned char keys[DFCRYPT_INTERNAL_AKEY_BYTES + DFCRYPT_INTERNAL_EKEY_BYTES];
    const unsigned char *akey = keys;
    const unsigned char *ekey = keys + DFCRYPT_INTERNAL_AKEY_BYTES;

    /* Sample a random salt and nonce. */
    randombytes_buf(salt, DFCRYPT_INTERNAL_SALT_BYTES);
    randombytes_buf(nonce, crypto_stream_chacha20_NONCEBYTES);

    /* Derive the authentication and encryption keys. */
    assert(sizeof(keys) == 64);
    crypto_generichash_blake2b_salt_personal(
        keys,                   /* output */
        sizeof(keys),           /* output length */
        state->appseed,         /* input */
        state->appseed_length,  /* input length */
        state->key,             /* key */
        DFCRYPT_KEY_BYTES,      /* key length */
        salt,                   /* salt */
        message_number          /* personalization (can be NULL) */
    );

    /* Encrypt the ciphertext. */
    crypto_stream_chacha20_xor(
        encrypted,      /* output */
        ptxt,           /* input */
        ptxt_len_bytes, /* input length */
        nonce,          /* nonce */
        ekey            /* key */
    );

    /* Append the MAC. */
    crypto_generichash_blake2b(
        mac,                            /* output */
        DFCRYPT_INTERNAL_MAC_BYTES,     /* output length */
        ctxt_out,                       /* input */
        DFCRYPT_INTERNAL_SALT_BYTES +
        crypto_stream_chacha20_NONCEBYTES + ptxt_len_bytes, /* input length */
        akey,                           /* key */
        DFCRYPT_INTERNAL_AKEY_BYTES     /* key length */
    );
}
Beispiel #4
0
uint8_t crypto_verifyAndDecrypt(const uint8_t* key, uint8_t* nonce, uint8_t* encrypted, uint8_t length, uint8_t* output_buf, uint8_t* mac)
{
  uint8_t polykey[sizeof(zeros64)];
  crypto_stream_chacha20_xor(polykey, zeros64, sizeof(zeros64), nonce, key, 0);

  uint8_t padding = (16 - length % 16) % 16;
  uint8_t message[length + padding + 16];
  memcpy(message, encrypted, length);
  memset(message + length, 0, padding + 16);
  message[length + padding + 8] = (uint8_t)length;
  message[length + padding + 9] = (uint8_t)(length >> 8);

  if (crypto_onetimeauth_poly1305_verify(mac, message, sizeof(message), polykey) != 0)
  {
    // Fail
    return 0;
  }
  else
  {
    crypto_stream_chacha20_xor(output_buf, message, length, nonce, key, 1);
    return 1;
  }
}
Beispiel #5
0
static
void tv(void)
{
    static struct {
        const char *key_hex;
        const char *nonce_hex;
    } tests[]
      = { { "0000000000000000000000000000000000000000000000000000000000000000",
            "0000000000000000" },
          { "0000000000000000000000000000000000000000000000000000000000000001",
            "0000000000000000" },
          { "0000000000000000000000000000000000000000000000000000000000000000",
            "0000000000000001" },
          { "0000000000000000000000000000000000000000000000000000000000000000",
            "0100000000000000" },
          { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
            "0001020304050607" } };
    unsigned char  key[crypto_stream_chacha20_KEYBYTES];
    unsigned char  nonce[crypto_stream_chacha20_NONCEBYTES];
    unsigned char *part;
    unsigned char  out[160];
    unsigned char  zero[160];
    char           out_hex[160 * 2 + 1];
    size_t         i = 0U;
    size_t         plen;

    memset(zero, 0, sizeof zero);
    do {
        sodium_hex2bin((unsigned char *)key, sizeof key, tests[i].key_hex,
                       strlen(tests[i].key_hex), NULL, NULL, NULL);
        sodium_hex2bin(nonce, sizeof nonce, tests[i].nonce_hex,
                       strlen(tests[i].nonce_hex), NULL, NULL, NULL);
        crypto_stream_chacha20(out, sizeof out, nonce, key);
        sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
        printf("[%s]\n", out_hex);
        for (plen = 1U; plen < sizeof out; plen++) {
            part = (unsigned char *) sodium_malloc(plen);
            crypto_stream_chacha20_xor(part, out, plen, nonce, key);
            if (memcmp(part, zero, plen) != 0) {
                printf("Failed with length %lu\n", (unsigned long) plen);
            }
            sodium_free(part);
        }
    } while (++i < (sizeof tests) / (sizeof tests[0]));

    randombytes_buf(out, sizeof out);
    crypto_stream_chacha20(out, sizeof out, nonce, key);
    sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
    printf("[%s]\n", out_hex);

    assert(crypto_stream_chacha20(out, 0U, nonce, key) == 0);
    assert(crypto_stream_chacha20_xor(out, out, 0U, nonce, key) == 0);
    assert(crypto_stream_chacha20_xor(out, out, 0U, nonce, key) == 0);
    assert(crypto_stream_chacha20_xor_ic(out, out, 0U, nonce, 1U, key) == 0);

    memset(out, 0x42, sizeof out);
    crypto_stream_chacha20_xor(out, out, sizeof out, nonce, key);
    sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
    printf("[%s]\n", out_hex);

    crypto_stream_chacha20_xor_ic(out, out, sizeof out, nonce, 0U, key);
    sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
    printf("[%s]\n", out_hex);

    crypto_stream_chacha20_xor_ic(out, out, sizeof out, nonce, 1U, key);
    sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out);
    printf("[%s]\n", out_hex);
};