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; }
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; }
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; }
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; }
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; } }
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; } }
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; } }
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; } }
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; } }
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; } }
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; } }
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; } }
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; } }