Beispiel #1
0
int
stream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)
{
    size_t nonce_len = cipher->nonce_len;
    int err          = CRYPTO_OK;

    if (ciphertext->len <= nonce_len) {
        return CRYPTO_ERROR;
    }

    cipher_ctx_t cipher_ctx;
    stream_ctx_init(cipher, &cipher_ctx, 0);

    static buffer_t tmp = { 0, 0, 0, NULL };
    brealloc(&tmp, ciphertext->len, capacity);
    buffer_t *plaintext = &tmp;
    plaintext->len = ciphertext->len - nonce_len;

    uint8_t *nonce = cipher_ctx.nonce;
    memcpy(nonce, ciphertext->data, nonce_len);

    if (ppbloom_check((void *)nonce, nonce_len) == 1) {
        LOGE("crypto: stream: repeat IV detected");
        return CRYPTO_ERROR;
    }

    cipher_ctx_set_nonce(&cipher_ctx, nonce, nonce_len, 0);

    if (cipher->method >= SALSA20) {
        crypto_stream_xor_ic((uint8_t *)plaintext->data,
                             (const uint8_t *)(ciphertext->data + nonce_len),
                             (uint64_t)(ciphertext->len - nonce_len),
                             (const uint8_t *)nonce, 0, cipher->key, cipher->method);
    } else {
        err = cipher_ctx_update(&cipher_ctx, (uint8_t *)plaintext->data, &plaintext->len,
                                (const uint8_t *)(ciphertext->data + nonce_len),
                                ciphertext->len - nonce_len);
    }

    stream_ctx_release(&cipher_ctx);

    if (err)
        return CRYPTO_ERROR;

#ifdef SS_DEBUG
    dump("PLAIN", plaintext->data, plaintext->len);
    dump("CIPHER", ciphertext->data + nonce_len, ciphertext->len - nonce_len);
    dump("NONCE", ciphertext->data, nonce_len);
#endif

    ppbloom_add((void *)nonce, nonce_len);

    brealloc(ciphertext, plaintext->len, capacity);
    memcpy(ciphertext->data, plaintext->data, plaintext->len);
    ciphertext->len = plaintext->len;

    return CRYPTO_OK;
}
Beispiel #2
0
int
aead_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)
{
    size_t salt_len = cipher->key_len;
    size_t tag_len  = cipher->tag_len;
    int err         = CRYPTO_OK;

    if (ciphertext->len <= salt_len + tag_len) {
        return CRYPTO_ERROR;
    }

    cipher_ctx_t cipher_ctx;
    aead_ctx_init(cipher, &cipher_ctx, 0);

    static buffer_t tmp = { 0, 0, 0, NULL };
    brealloc(&tmp, ciphertext->len, capacity);
    buffer_t *plaintext = &tmp;
    plaintext->len = ciphertext->len - salt_len - tag_len;

    /* get salt */
    uint8_t *salt = cipher_ctx.salt;
    memcpy(salt, ciphertext->data, salt_len);

    if (ppbloom_check((void *)salt, salt_len) == 1) {
        LOGE("crypto: AEAD: repeat salt detected");
        return CRYPTO_ERROR;
    }

    aead_cipher_ctx_set_key(&cipher_ctx, 0);

    size_t plen = plaintext->len;
    err = aead_cipher_decrypt(&cipher_ctx,
                              (uint8_t *)plaintext->data, &plen,
                              (uint8_t *)ciphertext->data + salt_len,
                              ciphertext->len - salt_len, NULL, 0,
                              cipher_ctx.nonce, cipher_ctx.skey);

    aead_ctx_release(&cipher_ctx);

    if (err)
        return CRYPTO_ERROR;

    ppbloom_add((void *)salt, salt_len);

    brealloc(ciphertext, plaintext->len, capacity);
    memcpy(ciphertext->data, plaintext->data, plaintext->len);
    ciphertext->len = plaintext->len;

    return CRYPTO_OK;
}
Beispiel #3
0
int
stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
{
    if (cipher_ctx == NULL)
        return CRYPTO_ERROR;

    cipher_t *cipher = cipher_ctx->cipher;

    static buffer_t tmp = { 0, 0, 0, NULL };

    int err = CRYPTO_OK;

    brealloc(&tmp, ciphertext->len, capacity);
    buffer_t *plaintext = &tmp;
    plaintext->len = ciphertext->len;

    if (!cipher_ctx->init) {
        if (cipher_ctx->chunk == NULL) {
            cipher_ctx->chunk = (buffer_t *)ss_malloc(sizeof(buffer_t));
            memset(cipher_ctx->chunk, 0, sizeof(buffer_t));
            balloc(cipher_ctx->chunk, cipher->nonce_len);
        }

        size_t left_len = min(cipher->nonce_len - cipher_ctx->chunk->len,
                              ciphertext->len);

        if (left_len > 0) {
            memcpy(cipher_ctx->chunk->data + cipher_ctx->chunk->len, ciphertext->data, left_len);
            memmove(ciphertext->data, ciphertext->data + left_len,
                    ciphertext->len - left_len);
            cipher_ctx->chunk->len += left_len;
            ciphertext->len        -= left_len;
        }

        if (cipher_ctx->chunk->len < cipher->nonce_len)
            return CRYPTO_NEED_MORE;

        uint8_t *nonce   = cipher_ctx->nonce;
        size_t nonce_len = cipher->nonce_len;
        plaintext->len -= left_len;

        memcpy(nonce, cipher_ctx->chunk->data, nonce_len);
        cipher_ctx_set_nonce(cipher_ctx, nonce, nonce_len, 0);
        cipher_ctx->counter = 0;
        cipher_ctx->init    = 1;

        if (cipher->method >= RC4_MD5) {
            if (ppbloom_check((void *)nonce, nonce_len) == 1) {
                LOGE("crypto: stream: repeat IV detected");
                return CRYPTO_ERROR;
            }
        }
    }

    if (ciphertext->len <= 0)
        return CRYPTO_NEED_MORE;

    if (cipher->method >= SALSA20) {
        int padding = cipher_ctx->counter % SODIUM_BLOCK_SIZE;
        brealloc(plaintext, (plaintext->len + padding) * 2, capacity);

        if (padding) {
            brealloc(ciphertext, ciphertext->len + padding, capacity);
            memmove(ciphertext->data + padding, ciphertext->data,
                    ciphertext->len);
            sodium_memzero(ciphertext->data, padding);
        }
        crypto_stream_xor_ic((uint8_t *)plaintext->data,
                             (const uint8_t *)(ciphertext->data),
                             (uint64_t)(ciphertext->len + padding),
                             (const uint8_t *)cipher_ctx->nonce,
                             cipher_ctx->counter / SODIUM_BLOCK_SIZE, cipher->key,
                             cipher->method);
        cipher_ctx->counter += ciphertext->len;
        if (padding) {
            memmove(plaintext->data, plaintext->data + padding, plaintext->len);
        }
    } else {
        err = cipher_ctx_update(cipher_ctx, (uint8_t *)plaintext->data, &plaintext->len,
                                (const uint8_t *)(ciphertext->data),
                                ciphertext->len);
    }

    if (err)
        return CRYPTO_ERROR;

#ifdef SS_DEBUG
    dump("PLAIN", plaintext->data, plaintext->len);
    dump("CIPHER", ciphertext->data, ciphertext->len);
#endif

    brealloc(ciphertext, plaintext->len, capacity);
    memcpy(ciphertext->data, plaintext->data, plaintext->len);
    ciphertext->len = plaintext->len;

    // Add to bloom filter
    if (cipher_ctx->init == 1) {
        if (cipher->method >= RC4_MD5) {
            ppbloom_add((void *)cipher_ctx->nonce, cipher->nonce_len);
            cipher_ctx->init = 2;
        }
    }

    return CRYPTO_OK;
}
Beispiel #4
0
int
aead_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
{
    int err             = CRYPTO_OK;
    static buffer_t tmp = { 0, 0, 0, NULL };

    cipher_t *cipher = cipher_ctx->cipher;

    size_t salt_len = cipher->key_len;

    if (cipher_ctx->chunk == NULL) {
        cipher_ctx->chunk = (buffer_t *)ss_malloc(sizeof(buffer_t));
        memset(cipher_ctx->chunk, 0, sizeof(buffer_t));
        balloc(cipher_ctx->chunk, capacity);
    }

    brealloc(cipher_ctx->chunk,
             cipher_ctx->chunk->len + ciphertext->len, capacity);
    memcpy(cipher_ctx->chunk->data + cipher_ctx->chunk->len,
           ciphertext->data, ciphertext->len);
    cipher_ctx->chunk->len += ciphertext->len;

    brealloc(&tmp, cipher_ctx->chunk->len, capacity);
    buffer_t *plaintext = &tmp;

    if (!cipher_ctx->init) {
        if (cipher_ctx->chunk->len <= salt_len)
            return CRYPTO_NEED_MORE;

        memcpy(cipher_ctx->salt, cipher_ctx->chunk->data, salt_len);

        aead_cipher_ctx_set_key(cipher_ctx, 0);

        if (ppbloom_check((void *)cipher_ctx->salt, salt_len) == 1) {
            LOGE("crypto: AEAD: repeat salt detected");
            return CRYPTO_ERROR;
        }

        memmove(cipher_ctx->chunk->data, cipher_ctx->chunk->data + salt_len,
                cipher_ctx->chunk->len - salt_len);
        cipher_ctx->chunk->len -= salt_len;

        cipher_ctx->init = 1;
    }

    size_t plen = 0;
    while (cipher_ctx->chunk->len > 0) {
        size_t chunk_clen = cipher_ctx->chunk->len;
        size_t chunk_plen = 0;
        err = aead_chunk_decrypt(cipher_ctx,
                                 (uint8_t *)plaintext->data + plen,
                                 (uint8_t *)cipher_ctx->chunk->data,
                                 cipher_ctx->nonce, &chunk_plen, &chunk_clen);
        if (err == CRYPTO_ERROR) {
            return err;
        } else if (err == CRYPTO_NEED_MORE) {
            if (plen == 0)
                return err;
            else
                break;
        }
        cipher_ctx->chunk->len = chunk_clen;
        plen                  += chunk_plen;
    }
    plaintext->len = plen;

    // Add the salt to bloom filter
    if (cipher_ctx->init == 1) {
        if (ppbloom_check((void *)cipher_ctx->salt, salt_len) == 1) {
            LOGE("crypto: AEAD: repeat salt detected");
            return CRYPTO_ERROR;
        }
        ppbloom_add((void *)cipher_ctx->salt, salt_len);
        cipher_ctx->init = 2;
    }

    brealloc(ciphertext, plaintext->len, capacity);
    memcpy(ciphertext->data, plaintext->data, plaintext->len);
    ciphertext->len = plaintext->len;

    return CRYPTO_OK;
}