char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method) { if (method > TABLE) { cipher_ctx_t evp; cipher_context_init(&evp, method, 1); int c_len = *len + BLOCK_SIZE; int iv_len = 0; int err = 0; char *ciphertext = malloc(max(iv_len + c_len, buf_size)); uint8_t iv[MAX_IV_LENGTH]; iv_len = enc_iv_len; cipher_context_set_iv(&evp, iv, iv_len, 1); memcpy(ciphertext, iv, iv_len); err = cipher_context_update(&evp, (uint8_t*)(ciphertext+iv_len), &c_len, (const uint8_t *)plaintext, *len); if (!err) { free(ciphertext); free(plaintext); cipher_context_release(&evp); return NULL; } #ifdef DEBUG dump("PLAIN", plaintext); dump("CIPHER", ciphertext); #endif *len = iv_len + c_len; free(plaintext); cipher_context_release(&evp); return ciphertext; } else { char *begin = plaintext; while (plaintext < begin + *len) { *plaintext = (char)enc_table[(uint8_t)*plaintext]; plaintext++; } return begin; } }
char* ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *ctx) { if (ctx != NULL) { int p_len = *len + BLOCK_SIZE; int iv_len = 0; int err = 0; char *plaintext = malloc(max(p_len, buf_size)); if (!ctx->init) { uint8_t iv[MAX_IV_LENGTH]; iv_len = enc_iv_len; memcpy(iv, ciphertext, iv_len); cipher_context_set_iv(&ctx->evp, iv, iv_len, 0); ctx->init = 1; } err = cipher_context_update(&ctx->evp, (uint8_t*)plaintext, &p_len, (const uint8_t*)(ciphertext + iv_len), *len - iv_len); if (!err) { free(ciphertext); free(plaintext); return NULL; } #ifdef DEBUG dump("PLAIN", plaintext); dump("CIPHER", ciphertext); #endif *len = p_len; free(ciphertext); return plaintext; } else { char *begin = ciphertext; while (ciphertext < begin + *len) { *ciphertext = (char)dec_table[(uint8_t)*ciphertext]; ciphertext++; } return begin; } }
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_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_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; } }
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; } }
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; } }