| /* |
| * Copyright (C) 2010 Martin Willi |
| * |
| * Copyright (C) secunet Security Networks AG |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the |
| * Free Software Foundation; either version 2 of the License, or (at your |
| * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * for more details. |
| */ |
| |
| #include <stdio.h> |
| #include <library.h> |
| |
| static int burn_crypter(const proposal_token_t *token, u_int limit, u_int len) |
| { |
| chunk_t iv, key, data; |
| crypter_t *crypter; |
| int i = 0; |
| bool ok; |
| |
| crypter = lib->crypto->create_crypter(lib->crypto, token->algorithm, |
| token->keysize / 8); |
| if (!crypter) |
| { |
| fprintf(stderr, "%N-%zu not supported\n", |
| encryption_algorithm_names, token->algorithm, token->keysize); |
| return FALSE; |
| } |
| |
| iv = chunk_alloc(crypter->get_iv_size(crypter)); |
| memset(iv.ptr, 0xFF, iv.len); |
| data = chunk_alloc(round_up(len, crypter->get_block_size(crypter))); |
| memset(data.ptr, 0xDD, data.len); |
| key = chunk_alloc(crypter->get_key_size(crypter)); |
| memset(key.ptr, 0xAA, key.len); |
| |
| ok = crypter->set_key(crypter, key); |
| while (ok) |
| { |
| if (!crypter->encrypt(crypter, data, iv, NULL)) |
| { |
| fprintf(stderr, "encryption failed!\n"); |
| ok = FALSE; |
| break; |
| } |
| if (!crypter->decrypt(crypter, data, iv, NULL)) |
| { |
| fprintf(stderr, "decryption failed!\n"); |
| ok = FALSE; |
| break; |
| } |
| if (limit && ++i == limit) |
| { |
| break; |
| } |
| } |
| crypter->destroy(crypter); |
| |
| free(iv.ptr); |
| free(data.ptr); |
| free(key.ptr); |
| |
| return ok; |
| } |
| |
| static bool burn_aead(const proposal_token_t *token, u_int limit, u_int len) |
| { |
| chunk_t iv, key, data, dataicv, assoc; |
| aead_t *aead; |
| int i = 0; |
| bool ok; |
| |
| aead = lib->crypto->create_aead(lib->crypto, token->algorithm, |
| token->keysize / 8, 0); |
| if (!aead) |
| { |
| fprintf(stderr, "%N-%zu not supported\n", |
| encryption_algorithm_names, token->algorithm, token->keysize); |
| return FALSE; |
| } |
| |
| iv = chunk_alloc(aead->get_iv_size(aead)); |
| memset(iv.ptr, 0xFF, iv.len); |
| dataicv = chunk_alloc(round_up(len, aead->get_block_size(aead)) + |
| aead->get_icv_size(aead)); |
| data = chunk_create(dataicv.ptr, dataicv.len - aead->get_icv_size(aead)); |
| memset(data.ptr, 0xDD, data.len); |
| assoc = chunk_alloc(13); |
| memset(assoc.ptr, 0xCC, assoc.len); |
| key = chunk_alloc(aead->get_key_size(aead)); |
| memset(key.ptr, 0xAA, key.len); |
| |
| ok = aead->set_key(aead, key); |
| while (ok) |
| { |
| if (!aead->encrypt(aead, data, assoc, iv, NULL)) |
| { |
| fprintf(stderr, "aead encryption failed!\n"); |
| ok = FALSE; |
| break; |
| } |
| if (!aead->decrypt(aead, dataicv, assoc, iv, NULL)) |
| { |
| fprintf(stderr, "aead integrity check failed!\n"); |
| ok = FALSE; |
| break; |
| } |
| if (limit && ++i == limit) |
| { |
| break; |
| } |
| } |
| aead->destroy(aead); |
| |
| free(iv.ptr); |
| free(data.ptr); |
| free(key.ptr); |
| free(assoc.ptr); |
| |
| return ok; |
| } |
| |
| static int burn_signer(const proposal_token_t *token, u_int limit, u_int len) |
| { |
| chunk_t key, data, sig; |
| signer_t *signer; |
| int i = 0; |
| bool ok; |
| |
| signer = lib->crypto->create_signer(lib->crypto, token->algorithm); |
| if (!signer) |
| { |
| fprintf(stderr, "%N not supported\n", |
| integrity_algorithm_names, token->algorithm); |
| return FALSE; |
| } |
| |
| data = chunk_alloc(len); |
| memset(data.ptr, 0xDD, data.len); |
| key = chunk_alloc(signer->get_key_size(signer)); |
| memset(key.ptr, 0xAA, key.len); |
| sig = chunk_alloc(signer->get_block_size(signer)); |
| |
| ok = signer->set_key(signer, key); |
| while (ok) |
| { |
| if (!signer->get_signature(signer, data, sig.ptr)) |
| { |
| fprintf(stderr, "creating signature failed!\n"); |
| ok = FALSE; |
| break; |
| } |
| if (!signer->verify_signature(signer, data, sig)) |
| { |
| fprintf(stderr, "verifying signature failed!\n"); |
| ok = FALSE; |
| break; |
| } |
| if (limit && ++i == limit) |
| { |
| break; |
| } |
| } |
| signer->destroy(signer); |
| |
| free(data.ptr); |
| free(key.ptr); |
| free(sig.ptr); |
| |
| return ok; |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| const proposal_token_t *token; |
| u_int limit = 0, len = 1024; |
| bool ok; |
| |
| library_init(NULL, "crypt_burn"); |
| lib->plugins->load(lib->plugins, getenv("PLUGINS") ?: PLUGINS); |
| atexit(library_deinit); |
| |
| fprintf(stderr, "loaded: %s\n", lib->plugins->loaded_plugins(lib->plugins)); |
| |
| if (argc < 2) |
| { |
| fprintf(stderr, "usage: %s <algorithm> [buflen=%u] [rounds=%u]\n", |
| argv[0], len, limit); |
| return 1; |
| } |
| if (argc > 2) |
| { |
| len = atoi(argv[2]); |
| if (len > (1 << 30)) |
| { |
| fprintf(stderr, "buffer too large (1 GiB limit)\n"); |
| return 1; |
| } |
| } |
| if (argc > 3) |
| { |
| limit = atoi(argv[3]); |
| } |
| |
| token = lib->proposal->get_token(lib->proposal, argv[1]); |
| if (!token) |
| { |
| fprintf(stderr, "algorithm '%s' unknown!\n", argv[1]); |
| return 1; |
| } |
| |
| switch (token->type) |
| { |
| case ENCRYPTION_ALGORITHM: |
| if (encryption_algorithm_is_aead(token->algorithm)) |
| { |
| ok = burn_aead(token, limit, len); |
| } |
| else |
| { |
| ok = burn_crypter(token, limit, len); |
| } |
| break; |
| case INTEGRITY_ALGORITHM: |
| ok = burn_signer(token, limit, len); |
| break; |
| default: |
| fprintf(stderr, "'%s' is not a crypter/aead algorithm!\n", argv[1]); |
| ok = FALSE; |
| break; |
| } |
| return !ok; |
| } |