static int process_file(struct rsa_session *ctx, FILE *in, FILE *out) { uint8_t buffer[BLOCK_SIZE + SHA1_DIGEST_SIZE]; for (;;) { size_t size = fread(buffer, 1, BLOCK_SIZE, in); hmac_sha1_update(&ctx->hmac, size, buffer); if (size < BLOCK_SIZE) { unsigned leftover; unsigned padding; if (ferror(in)) { werror("Reading input failed: %s\n", strerror(errno)); return 0; } leftover = size % AES_BLOCK_SIZE; padding = AES_BLOCK_SIZE - leftover; assert (size + padding <= BLOCK_SIZE); if (padding > 1) yarrow256_random(&ctx->yarrow, padding - 1, buffer + size); size += padding; buffer[size - 1] = padding; CBC_ENCRYPT(&ctx->aes, aes_encrypt, size, buffer, buffer); assert (size + SHA1_DIGEST_SIZE <= sizeof(buffer)); hmac_sha1_digest(&ctx->hmac, SHA1_DIGEST_SIZE, buffer + size); size += SHA1_DIGEST_SIZE; if (!write_string(out, size, buffer)) { werror("Writing output failed: %s\n", strerror(errno)); return 0; } return 1; } CBC_ENCRYPT(&ctx->aes, aes_encrypt, size, buffer, buffer); if (!write_string(out, size, buffer)) { werror("Writing output failed: %s\n", strerror(errno)); return 0; } } }
term_t cbif_sha_mac_n3(proc_t *proc, term_t *regs) { term_t Key = regs[0]; term_t Data = regs[1]; term_t Size = regs[2]; if (!is_list(Key) && !is_boxed_binary(Key)) badarg(Key); if (!is_list(Data) && !is_boxed_binary(Data)) badarg(Data); if (!is_int(Size)) badarg(Size); int trunc_size = int_value(Size); if (trunc_size < 1 || trunc_size > SHA1_DIGEST_SIZE) badarg(Size); int key_size = iolist_size(Key); if (key_size < 0) badarg(Key); assert(key_size <= 65536); // TODO: use heap_tmp_buf for a longer Key uint8_t key_buf[key_size]; iolist_flatten(Key, key_buf); int data_size = iolist_size(Data); if (data_size < 0) badarg(Data); assert(data_size <= 65536); // TODO: use heap_tmp_buf for larger Data uint8_t data_buf[data_size]; iolist_flatten(Data, data_buf); struct hmac_sha1_ctx ctx; hmac_sha1_set_key(&ctx, key_size, key_buf); hmac_sha1_update(&ctx, data_size, data_buf); uint8_t *ptr; term_t mac = heap_make_bin(&proc->hp, trunc_size, &ptr); hmac_sha1_digest(&ctx, trunc_size, ptr); return mac; }
static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) { hmac_sha1_digest(ctx, (unsigned)*out_len, out); }
static int process_file(struct rsa_session *ctx, FILE *in, FILE *out) { uint8_t buffer[BUF_SIZE + BUF_FINAL]; uint8_t digest[SHA1_DIGEST_SIZE]; size_t size; unsigned padding; size = fread(buffer, 1, BUF_FINAL, in); if (size < BUF_FINAL) { if (ferror(in)) werror("Reading input failed: %s\n", strerror(errno)); else werror("Unexpected EOF on input.\n"); return 0; } do { size = fread(buffer + BUF_FINAL, 1, BUF_SIZE, in); if (size < BUF_SIZE && ferror(in)) { werror("Reading input failed: %s\n", strerror(errno)); return 0; } if (size % AES_BLOCK_SIZE != 0) { werror("Unexpected EOF on input.\n"); return 0; } if (size) { CBC_DECRYPT(&ctx->aes, aes256_decrypt, size, buffer, buffer); hmac_sha1_update(&ctx->hmac, size, buffer); if (!write_data(out, size, buffer)) { werror("Writing output failed: %s\n", strerror(errno)); return 0; } memmove(buffer, buffer + size, BUF_FINAL); } } while (size == BUF_SIZE); /* Decrypt final block */ CBC_DECRYPT(&ctx->aes, aes256_decrypt, AES_BLOCK_SIZE, buffer, buffer); padding = buffer[AES_BLOCK_SIZE - 1]; if (padding > AES_BLOCK_SIZE) { werror("Decryption failed: Invalid padding.\n"); return 0; } if (padding < AES_BLOCK_SIZE) { unsigned leftover = AES_BLOCK_SIZE - padding; hmac_sha1_update(&ctx->hmac, leftover, buffer); if (!write_data(out, leftover, buffer)) { werror("Writing output failed: %s\n", strerror(errno)); return 0; } } hmac_sha1_digest(&ctx->hmac, SHA1_DIGEST_SIZE, digest); if (!memeql_sec(digest, buffer + AES_BLOCK_SIZE, SHA1_DIGEST_SIZE)) { werror("Decryption failed: Invalid mac.\n"); return 0; } return 1; }