コード例 #1
0
ファイル: stream.c プロジェクト: Wang-P/shadowsocks-libev
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;
}
コード例 #2
0
ファイル: stream.c プロジェクト: Wang-P/shadowsocks-libev
int
stream_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity)
{
    cipher_ctx_t cipher_ctx;
    stream_ctx_init(cipher, &cipher_ctx, 1);

    size_t nonce_len = cipher->nonce_len;
    int err          = CRYPTO_OK;

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

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

    if (cipher->method >= SALSA20) {
        crypto_stream_xor_ic((uint8_t *)(ciphertext->data + nonce_len),
                             (const uint8_t *)plaintext->data, (uint64_t)(plaintext->len),
                             (const uint8_t *)nonce,
                             0, cipher->key, cipher->method);
    } else {
        err = cipher_ctx_update(&cipher_ctx, (uint8_t *)(ciphertext->data + nonce_len),
                                &ciphertext->len, (const uint8_t *)plaintext->data,
                                plaintext->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);
    dump("NONCE", ciphertext->data, nonce_len);
#endif

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

    return CRYPTO_OK;
}
コード例 #3
0
ファイル: stream.c プロジェクト: Wang-P/shadowsocks-libev
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;
}
コード例 #4
0
ファイル: stream.c プロジェクト: Wang-P/shadowsocks-libev
int
stream_encrypt(buffer_t *plaintext, 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;
    size_t nonce_len = 0;
    if (!cipher_ctx->init) {
        nonce_len = cipher_ctx->cipher->nonce_len;
    }

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

    if (!cipher_ctx->init) {
        cipher_ctx_set_nonce(cipher_ctx, cipher_ctx->nonce, nonce_len, 1);
        memcpy(ciphertext->data, cipher_ctx->nonce, nonce_len);
        cipher_ctx->counter = 0;
        cipher_ctx->init    = 1;
    }

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

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

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

    return CRYPTO_OK;
}
コード例 #5
0
ファイル: encrypt.c プロジェクト: 3gao/shadowsocks-libev
int ss_decrypt_all(buffer_t *cipher, int method, int auth, size_t capacity)
{
    if (method > TABLE) {
        size_t iv_len = enc_iv_len;
        int ret       = 1;

        if (cipher->len <= iv_len) {
            return -1;
        }

        cipher_ctx_t evp;
        cipher_context_init(&evp, method, 0);

        static buffer_t tmp = { 0, 0, 0, NULL };
        brealloc(&tmp, cipher->len, capacity);
        buffer_t *plain = &tmp;
        plain->len = cipher->len - iv_len;

        uint8_t iv[MAX_IV_LENGTH];
        memcpy(iv, cipher->array, iv_len);
        cipher_context_set_iv(&evp, iv, iv_len, 0);

        if (method >= SALSA20) {
            crypto_stream_xor_ic((uint8_t *)plain->array,
                                 (const uint8_t *)(cipher->array + iv_len),
                                 (uint64_t)(cipher->len - iv_len),
                                 (const uint8_t *)iv, 0, enc_key, method);
        } else {
            ret = cipher_context_update(&evp, (uint8_t *)plain->array, &plain->len,
                                        (const uint8_t *)(cipher->array + iv_len),
                                        cipher->len - iv_len);
        }

        if (auth || (plain->array[0] & ONETIMEAUTH_FLAG)) {
            if (plain->len > ONETIMEAUTH_BYTES) {
                ret = !ss_onetimeauth_verify(plain, iv);
                if (ret) {
                    plain->len -= ONETIMEAUTH_BYTES;
                }
            } else {
                ret = 0;
            }
        }

        if (!ret) {
            bfree(cipher);
            cipher_context_release(&evp);
            return -1;
        }

#ifdef DEBUG
        dump("PLAIN", plain->array, plain->len);
        dump("CIPHER", cipher->array + iv_len, cipher->len - iv_len);
#endif

        cipher_context_release(&evp);

        brealloc(cipher, plain->len, capacity);
        memcpy(cipher->array, plain->array, plain->len);
        cipher->len = plain->len;

        return 0;
    } else {
        char *begin = cipher->array;
        char *ptr   = cipher->array;
        while (ptr < begin + cipher->len) {
            *ptr = (char)dec_table[(uint8_t)*ptr];
            ptr++;
        }
        return 0;
    }
}
コード例 #6
0
ファイル: encrypt.c プロジェクト: 3gao/shadowsocks-libev
int ss_decrypt(buffer_t *cipher, enc_ctx_t *ctx, size_t capacity)
{
    if (ctx != NULL) {
        static buffer_t tmp = { 0, 0, 0, NULL };

        size_t iv_len = 0;
        int err       = 1;

        brealloc(&tmp, cipher->len, capacity);
        buffer_t *plain = &tmp;
        plain->len = cipher->len;

        if (!ctx->init) {
            uint8_t iv[MAX_IV_LENGTH];
            iv_len      = enc_iv_len;
            plain->len -= iv_len;

            memcpy(iv, cipher->array, iv_len);
            cipher_context_set_iv(&ctx->evp, iv, iv_len, 0);
            ctx->counter = 0;
            ctx->init    = 1;

            if (enc_method >= RC4_MD5) {
                if (cache_key_exist(iv_cache, (char *)iv, iv_len)) {
                    bfree(cipher);
                    return -1;
                } else {
                    cache_insert(iv_cache, (char *)iv, iv_len, NULL);
                }
            }
        }

        if (enc_method >= SALSA20) {
            int padding = ctx->counter % SODIUM_BLOCK_SIZE;
            brealloc(plain, (plain->len + padding) * 2, capacity);

            if (padding) {
                brealloc(cipher, cipher->len + padding, capacity);
                memmove(cipher->array + iv_len + padding, cipher->array + iv_len,
                        cipher->len - iv_len);
                memset(cipher->array + iv_len, 0, padding);
            }
            crypto_stream_xor_ic((uint8_t *)plain->array,
                                 (const uint8_t *)(cipher->array + iv_len),
                                 (uint64_t)(cipher->len - iv_len + padding),
                                 (const uint8_t *)ctx->evp.iv,
                                 ctx->counter / SODIUM_BLOCK_SIZE, enc_key,
                                 enc_method);
            ctx->counter += cipher->len - iv_len;
            if (padding) {
                memmove(plain->array, plain->array + padding, plain->len);
            }
        } else {
            err = cipher_context_update(&ctx->evp, (uint8_t *)plain->array, &plain->len,
                                        (const uint8_t *)(cipher->array + iv_len),
                                        cipher->len - iv_len);
        }

        if (!err) {
            bfree(cipher);
            return -1;
        }

#ifdef DEBUG
        dump("PLAIN", plain->array, plain->len);
        dump("CIPHER", cipher->array + iv_len, cipher->len - iv_len);
#endif

        brealloc(cipher, plain->len, capacity);
        memcpy(cipher->array, plain->array, plain->len);
        cipher->len = plain->len;

        return 0;
    } else {
        char *begin = cipher->array;
        char *ptr   = cipher->array;
        while (ptr < begin + cipher->len) {
            *ptr = (char)dec_table[(uint8_t)*ptr];
            ptr++;
        }
        return 0;
    }
}
コード例 #7
0
ファイル: encrypt.c プロジェクト: 3gao/shadowsocks-libev
int ss_encrypt_all(buffer_t *plain, int method, int auth, size_t capacity)
{
    if (method > TABLE) {
        cipher_ctx_t evp;
        cipher_context_init(&evp, method, 1);

        size_t iv_len = enc_iv_len;
        int err       = 1;

        static buffer_t tmp = { 0, 0, 0, NULL };
        brealloc(&tmp, iv_len + plain->len, capacity);
        buffer_t *cipher = &tmp;
        cipher->len = plain->len;

        uint8_t iv[MAX_IV_LENGTH];

        rand_bytes(iv, iv_len);
        cipher_context_set_iv(&evp, iv, iv_len, 1);
        memcpy(cipher->array, iv, iv_len);

        if (auth) {
            ss_onetimeauth(plain, iv, capacity);
            cipher->len = plain->len;
        }

        if (method >= SALSA20) {
            crypto_stream_xor_ic((uint8_t *)(cipher->array + iv_len),
                                 (const uint8_t *)plain->array, (uint64_t)(plain->len),
                                 (const uint8_t *)iv,
                                 0, enc_key, method);
        } else {
            err = cipher_context_update(&evp, (uint8_t *)(cipher->array + iv_len),
                                        &cipher->len, (const uint8_t *)plain->array,
                                        plain->len);
        }

        if (!err) {
            bfree(plain);
            cipher_context_release(&evp);
            return -1;
        }

#ifdef DEBUG
        dump("PLAIN", plain->array, plain->len);
        dump("CIPHER", cipher->array + iv_len, cipher->len);
#endif

        cipher_context_release(&evp);

        brealloc(plain, iv_len + cipher->len, capacity);
        memcpy(plain->array, cipher->array, iv_len + cipher->len);
        plain->len = iv_len + cipher->len;

        return 0;
    } else {
        char *begin = plain->array;
        char *ptr   = plain->array;
        while (ptr < begin + plain->len) {
            *ptr = (char)enc_table[(uint8_t)*ptr];
            ptr++;
        }
        return 0;
    }
}
コード例 #8
0
ファイル: encrypt.c プロジェクト: 3gao/shadowsocks-libev
int ss_encrypt(buffer_t *plain, enc_ctx_t *ctx, size_t capacity)
{
    if (ctx != NULL) {
        static buffer_t tmp = { 0, 0, 0, NULL };

        int err       = 1;
        size_t iv_len = 0;
        if (!ctx->init) {
            iv_len = enc_iv_len;
        }

        brealloc(&tmp, iv_len + plain->len, capacity);
        buffer_t *cipher = &tmp;
        cipher->len = plain->len;

        if (!ctx->init) {
            cipher_context_set_iv(&ctx->evp, ctx->evp.iv, iv_len, 1);
            memcpy(cipher->array, ctx->evp.iv, iv_len);
            ctx->counter = 0;
            ctx->init    = 1;
        }

        if (enc_method >= SALSA20) {
            int padding = ctx->counter % SODIUM_BLOCK_SIZE;
            brealloc(cipher, iv_len + (padding + cipher->len) * 2, capacity);
            if (padding) {
                brealloc(plain, plain->len + padding, capacity);
                memmove(plain->array + padding, plain->array, plain->len);
                memset(plain->array, 0, padding);
            }
            crypto_stream_xor_ic((uint8_t *)(cipher->array + iv_len),
                                 (const uint8_t *)plain->array,
                                 (uint64_t)(plain->len + padding),
                                 (const uint8_t *)ctx->evp.iv,
                                 ctx->counter / SODIUM_BLOCK_SIZE, enc_key,
                                 enc_method);
            ctx->counter += plain->len;
            if (padding) {
                memmove(cipher->array + iv_len,
                        cipher->array + iv_len + padding, cipher->len);
            }
        } else {
            err =
                cipher_context_update(&ctx->evp,
                                      (uint8_t *)(cipher->array + iv_len),
                                      &cipher->len, (const uint8_t *)plain->array,
                                      plain->len);
            if (!err) {
                return -1;
            }
        }

#ifdef DEBUG
        dump("PLAIN", plain->array, plain->len);
        dump("CIPHER", cipher->array + iv_len, cipher->len);
#endif

        brealloc(plain, iv_len + cipher->len, capacity);
        memcpy(plain->array, cipher->array, iv_len + cipher->len);
        plain->len = iv_len + cipher->len;

        return 0;
    } else {
        char *begin = plain->array;
        char *ptr   = plain->array;
        while (ptr < begin + plain->len) {
            *ptr = (char)enc_table[(uint8_t)*ptr];
            ptr++;
        }
        return 0;
    }
}
コード例 #9
0
ファイル: encrypt.c プロジェクト: Arathi/ShadowsocksRDroid
char * ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *ctx)
{
    if (ctx != NULL) {
        static int tmp_len = 0;
        static char *tmp_buf = NULL;

        size_t c_len = *len, p_len = *len;
        size_t iv_len = 0;
        int err = 1;
        int buf_len = max(p_len, buf_size);

        if (tmp_len < buf_len) {
            tmp_len = buf_len;
            tmp_buf = realloc(tmp_buf, buf_len);
        }
        char *plaintext = tmp_buf;

        if (!ctx->init) {
            uint8_t iv[MAX_IV_LENGTH];
            iv_len = enc_iv_len;
            p_len -= iv_len;
            memcpy(iv, ciphertext, iv_len);
            cipher_context_set_iv(&ctx->evp, iv, iv_len, 0);
            ctx->counter = 0;
            ctx->init = 1;

            if (enc_method >= RC4_MD5) {
                if (cache_key_exist(iv_cache, (char *)iv, iv_len)) {
                    free(ciphertext);
                    return NULL;
                } else {
                    cache_insert(iv_cache, (char *)iv, iv_len, NULL);
                }
            }
        }

        if (enc_method >= SALSA20) {
            int padding = ctx->counter % SODIUM_BLOCK_SIZE;
            if (buf_len < (p_len + padding) * 2) {
                buf_len = max((p_len + padding) * 2, buf_size);
                plaintext = realloc(plaintext, buf_len);
                tmp_len = buf_len;
                tmp_buf = plaintext;
            }
            if (padding) {
                ciphertext = realloc(ciphertext, max(c_len + padding, buf_size));
                memmove(ciphertext + iv_len + padding, ciphertext + iv_len,
                        c_len - iv_len);
                memset(ciphertext + iv_len, 0, padding);
            }
            crypto_stream_xor_ic((uint8_t *)plaintext,
                                 (const uint8_t *)(ciphertext + iv_len),
                                 (uint64_t)(c_len - iv_len + padding),
                                 (const uint8_t *)ctx->evp.iv,
                                 ctx->counter / SODIUM_BLOCK_SIZE, enc_key,
                                 enc_method);
            ctx->counter += c_len - iv_len;
            if (padding) {
                memmove(plaintext, plaintext + padding, p_len);
            }
        } else {
            err = cipher_context_update(&ctx->evp, (uint8_t *)plaintext, &p_len,
                                        (const uint8_t *)(ciphertext + iv_len),
                                        c_len - iv_len);
        }

        if (!err) {
            free(ciphertext);
            return NULL;
        }

#ifdef DEBUG
        dump("PLAIN", plaintext, p_len);
        dump("CIPHER", ciphertext + iv_len, c_len - iv_len);
#endif

        if (buf_size < p_len) {
            ciphertext = realloc(ciphertext, p_len);
        }
        *len = p_len;
        memcpy(ciphertext, plaintext, *len);

        return ciphertext;
    } else {
        char *begin = ciphertext;
        while (ciphertext < begin + *len) {
            *ciphertext = (char)dec_table[(uint8_t)*ciphertext];
            ciphertext++;
        }
        return begin;
    }
}
コード例 #10
0
ファイル: encrypt.c プロジェクト: Arathi/ShadowsocksRDroid
char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method, int auth)
{
    if (method > TABLE) {
        size_t iv_len = enc_iv_len;
        size_t c_len = *len, p_len = *len - iv_len;
        int ret = 1;

        if (*len <= iv_len) {
            return NULL;
        }

        cipher_ctx_t evp;
        cipher_context_init(&evp, method, 0);

        static int tmp_len = 0;
        static char *tmp_buf = NULL;
        int buf_len = max(p_len, buf_size);
        if (tmp_len < buf_len) {
            tmp_len = buf_len;
            tmp_buf = realloc(tmp_buf, buf_len);
        }
        char *plaintext = tmp_buf;

        uint8_t iv[MAX_IV_LENGTH];
        memcpy(iv, ciphertext, iv_len);
        cipher_context_set_iv(&evp, iv, iv_len, 0);

        if (method >= SALSA20) {
            crypto_stream_xor_ic((uint8_t *)plaintext,
                                 (const uint8_t *)(ciphertext + iv_len),
                                 (uint64_t)(c_len - iv_len),
                                 (const uint8_t *)iv, 0, enc_key, method);
        } else {
            ret = cipher_context_update(&evp, (uint8_t *)plaintext, &p_len,
                                        (const uint8_t *)(ciphertext + iv_len),
                                        c_len - iv_len);
        }

        if (auth || (plaintext[0] & ONETIMEAUTH_FLAG)) {
            if (p_len > ONETIMEAUTH_BYTES) {
                char hash[ONETIMEAUTH_BYTES];
                memcpy(hash, plaintext + p_len - ONETIMEAUTH_BYTES, ONETIMEAUTH_BYTES);
                ret = !ss_onetimeauth_verify(hash, plaintext, p_len - ONETIMEAUTH_BYTES, iv);
                if (ret) {
                    p_len -= ONETIMEAUTH_BYTES;
                }
            } else {
                ret = 0;
            }
        }

        if (!ret) {
            free(ciphertext);
            cipher_context_release(&evp);
            return NULL;
        }

#ifdef DEBUG
        dump("PLAIN", plaintext, p_len);
        dump("CIPHER", ciphertext + iv_len, c_len - iv_len);
#endif

        cipher_context_release(&evp);

        if (buf_size < p_len) {
            ciphertext = realloc(ciphertext, p_len);
        }
        *len = p_len;
        memcpy(ciphertext, plaintext, *len);

        return ciphertext;
    } else {
        char *begin = ciphertext;
        while (ciphertext < begin + *len) {
            *ciphertext = (char)dec_table[(uint8_t)*ciphertext];
            ciphertext++;
        }
        return begin;
    }
}
コード例 #11
0
ファイル: encrypt.c プロジェクト: Arathi/ShadowsocksRDroid
char * ss_encrypt(int buf_size, char *plaintext, ssize_t *len,
                  struct enc_ctx *ctx)
{
    if (ctx != NULL) {
        static int tmp_len = 0;
        static char *tmp_buf = NULL;

        int err = 1;
        size_t iv_len = 0;
        size_t p_len = *len, c_len = *len;
        if (!ctx->init) {
            iv_len = enc_iv_len;
        }

        int buf_len = max(iv_len + c_len, buf_size);
        if (tmp_len < buf_len) {
            tmp_len = buf_len;
            tmp_buf = realloc(tmp_buf, buf_len);
        }
        char *ciphertext = tmp_buf;

        if (!ctx->init) {
            cipher_context_set_iv(&ctx->evp, ctx->evp.iv, iv_len, 1);
            memcpy(ciphertext, ctx->evp.iv, iv_len);
            ctx->counter = 0;
            ctx->init = 1;
        }

        if (enc_method >= SALSA20) {
            int padding = ctx->counter % SODIUM_BLOCK_SIZE;
            if (buf_len < iv_len + padding + c_len) {
                buf_len = max(iv_len + (padding + c_len) * 2, buf_size);
                ciphertext = realloc(ciphertext, buf_len);
                tmp_len = buf_len;
                tmp_buf = ciphertext;
            }
            if (padding) {
                plaintext = realloc(plaintext, max(p_len + padding, buf_size));
                memmove(plaintext + padding, plaintext, p_len);
                memset(plaintext, 0, padding);
            }
            crypto_stream_xor_ic((uint8_t *)(ciphertext + iv_len),
                                 (const uint8_t *)plaintext,
                                 (uint64_t)(p_len + padding),
                                 (const uint8_t *)ctx->evp.iv,
                                 ctx->counter / SODIUM_BLOCK_SIZE, enc_key,
                                 enc_method);
            ctx->counter += p_len;
            if (padding) {
                memmove(ciphertext + iv_len, ciphertext + iv_len + padding,
                        c_len);
            }
        } else {
            err =
                cipher_context_update(&ctx->evp,
                                      (uint8_t *)(ciphertext + iv_len),
                                      &c_len, (const uint8_t *)plaintext,
                                      p_len);
            if (!err) {
                free(plaintext);
                return NULL;
            }
        }

#ifdef DEBUG
        dump("PLAIN", plaintext, p_len);
        dump("CIPHER", ciphertext + iv_len, c_len);
#endif

        if (buf_size < iv_len + c_len) {
            plaintext = realloc(plaintext, iv_len + c_len);
        }
        *len = iv_len + c_len;
        memcpy(plaintext, ciphertext, *len);

        return plaintext;
    } else {
        char *begin = plaintext;
        while (plaintext < begin + *len) {
            *plaintext = (char)enc_table[(uint8_t)*plaintext];
            plaintext++;
        }
        return begin;
    }
}
コード例 #12
0
ファイル: encrypt.c プロジェクト: Arathi/ShadowsocksRDroid
char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method, int auth)
{
    if (method > TABLE) {
        cipher_ctx_t evp;
        cipher_context_init(&evp, method, 1);

        size_t p_len = *len, c_len = *len;
        size_t iv_len = enc_iv_len;
        int err = 1;

        static int tmp_len = 0;
        static char *tmp_buf = NULL;
        int buf_len = max(iv_len + c_len, buf_size);
        if (tmp_len < buf_len) {
            tmp_len = buf_len;
            tmp_buf = realloc(tmp_buf, buf_len);
        }
        char *ciphertext = tmp_buf;

        uint8_t iv[MAX_IV_LENGTH];

        rand_bytes(iv, iv_len);
        cipher_context_set_iv(&evp, iv, iv_len, 1);
        memcpy(ciphertext, iv, iv_len);

        if (auth) {
            char hash[ONETIMEAUTH_BYTES * 2];
            ss_onetimeauth(hash, plaintext, p_len, iv);
            if (buf_size < ONETIMEAUTH_BYTES + p_len) {
                plaintext = realloc(plaintext, ONETIMEAUTH_BYTES + p_len);
            }
            memcpy(plaintext + p_len, hash, ONETIMEAUTH_BYTES);
            p_len = c_len = p_len + ONETIMEAUTH_BYTES;
        }

        if (method >= SALSA20) {
            crypto_stream_xor_ic((uint8_t *)(ciphertext + iv_len),
                                 (const uint8_t *)plaintext, (uint64_t)(p_len),
                                 (const uint8_t *)iv,
                                 0, enc_key, method);
        } else {
            err = cipher_context_update(&evp, (uint8_t *)(ciphertext + iv_len),
                                        &c_len, (const uint8_t *)plaintext,
                                        p_len);
        }

        if (!err) {
            free(plaintext);
            cipher_context_release(&evp);
            return NULL;
        }

#ifdef DEBUG
        dump("PLAIN", plaintext, *len);
        dump("CIPHER", ciphertext + iv_len, c_len);
#endif

        cipher_context_release(&evp);

        if (buf_size < iv_len + c_len) {
            plaintext = realloc(plaintext, iv_len + c_len);
        }
        *len = iv_len + c_len;
        memcpy(plaintext, ciphertext, *len);

        return plaintext;
    } else {
        char *begin = plaintext;
        while (plaintext < begin + *len) {
            *plaintext = (char)enc_table[(uint8_t)*plaintext];
            plaintext++;
        }
        return begin;
    }
}
コード例 #13
0
ファイル: encrypt.c プロジェクト: nezharen/shadowsocks-libev
char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method)
{
    if (method > TABLE) {
        cipher_ctx_t evp;
        cipher_context_init(&evp, method, 0);
        int iv_len = enc_iv_len;
        int c_len = *len, p_len = *len - iv_len;
        int err = 1;

        static int tmp_len = 0;
        static char *tmp_buf = NULL;
        int buf_len = max(p_len, buf_size);
        if (tmp_len < buf_len) {
            tmp_len = buf_len;
            tmp_buf = realloc(tmp_buf, buf_len);
        }
        char *plaintext = tmp_buf;

        uint8_t iv[MAX_IV_LENGTH];
        memcpy(iv, ciphertext, iv_len);
        cipher_context_set_iv(&evp, iv, iv_len, 0);

        if (method >= SALSA20) {
            crypto_stream_xor_ic((uint8_t *)plaintext,
                                 (const uint8_t *)(ciphertext + iv_len),
                                 (uint64_t)(c_len - iv_len),
                                 (const uint8_t *)iv, 0, enc_key, method);
        } else {
            err = cipher_context_update(&evp, (uint8_t *)plaintext, &p_len,
                                        (const uint8_t *)(ciphertext + iv_len),
                                        c_len - iv_len);
        }

        if (!err) {
            free(ciphertext);
            cipher_context_release(&evp);
            return NULL;
        }

#ifdef DEBUG
        dump("PLAIN", plaintext, p_len);
        dump("CIPHER", ciphertext + iv_len, c_len - iv_len);
#endif

        cipher_context_release(&evp);

        if (*len < p_len) {
            ciphertext = realloc(ciphertext, max(p_len, buf_size));
        }
        *len = p_len;
        memcpy(ciphertext, plaintext, *len);

        return ciphertext;
    } else {
        char *begin = ciphertext;
        while (ciphertext < begin + *len) {
            *ciphertext = (char)dec_table[(uint8_t)*ciphertext];
            ciphertext++;
        }
        return begin;
    }
}