void enc_ctx_init(int method, enc_ctx_t *ctx, int enc) { memset(ctx, 0, sizeof(enc_ctx_t)); cipher_context_init(&ctx->evp, method, enc); if (enc) { rand_bytes(ctx->evp.iv, enc_iv_len); } }
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; } }
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_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; } }
void enc_ctx_init(int method, struct enc_ctx *ctx, int enc) { memset(ctx, 0, sizeof(struct enc_ctx)); cipher_context_init(&ctx->evp, method, enc); }
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_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; } }