📄 password.c
字号:
/* * GNU POC (passwords on card) - manage passwords on smartcards * Copyright (C) 2001 Henning Koester <henning@crackinghacking.de> * * Please report bugs to bug-poc@gnu.org * * This file is part of POC. * * 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. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* $Id: password.c,v 1.8 2001/08/18 16:15:43 henning Exp $ */#include <config.h>#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <errno.h>#ifdef HAVE_BYTESWAP_H #include <byteswap.h>#else#include "missing_libs.h"#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "cardinfo.h"#include "card.h"#include "lang.h"#include "poc.h"#include "poc_types.h"#include "poc_macros.h"#include "cipher.h"#include "misc.h"/****************************************************************************** * * Function : search_free_space * * Description : This function checks whether there's still enough free memory * on the card to store the new password+description. * * Input : [1] needed_space (int) * Size of password+description+2 byte 'size of the tags'. * [2] buffer (u8) * This buffer is checked for enough free space. * [3] used_space (int) * Used space of 'buffer'. * [4] buffer_size (int) * Buffer's size. * * Return : -1 (not enough space left), 0 (enough free space) * *****************************************************************************/static int search_free_space(const int needed_space, const u8 * const buffer, const int used_space, const int buffer_size) { if (buffer_size - used_space < needed_space) return(-1); return(0);}/* Clean sensetive data. */#define wipe_out_data() { \ overwrite_buffer(password); \ overwrite_buffer(p); \ overwrite_buffer(key); \ overwrite_buffer(buffer); \ drop_mbuffer(buffer); \}/****************************************************************************** * * Function : password_save * * Description : This function saves a password on the card. * * Input : [1] card_crypt_ctx (crypt_context) * Information about data encryption (cipher, security-level) * [2] port (u16) * Com-Port * * Return : POC_ERROR or POC_SUCCESS * *****************************************************************************/bool password_save(const crypt_context * const card_crypt_ctx, const u16 port) { char description[DESCR_LENGTH]; /* Description of the password. */ char password[128]; /* Password which will be saved. */ char key[128]; /* Key for card encryption. */ u8 *buffer = NULL; /* Buffer for card-data. */ u16 data_size; /* Used space on the card (in byte). */ u16 card_size; /* Card's size. */ char *p; /* Pointer for getpass(). */ char ret; /* used to store returns of card func. */ u16 ctn = 0; /* Card-terminal handle. */ int position; /* Offset where free-memory is found. */ /* Get the password which shall be saved. */ if ((p = getpass(STR_PASSWORD_PROMPT)) == NULL) return(POC_ERROR); strncpy(password, p, 128); /* Save it in 'password'. */ /* Get password's description. */ printf(STR_DESCR_PROMPT); fgets(description, DESCR_LENGTH, stdin); description[strlen(description) - 1] = '\0'; /* Initialize & reset card terminal. */ if ( (card_init_terminal(ctn, port) != POC_SUCCESS) || (card_reset_terminal(ctn) != POC_SUCCESS) ) { /* If initialization fails, or resetting, we will return. */ wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Request ICC and check whether a memory card is inserted. */ if (card_request_icc(ctn) != MEMORY_CARD) { /* If no memory card is present we will return. */ print_err(STR_NO_MEM_CARD); wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Select card's memory for reading and writing. */ if (card_select_file(ctn) != POC_SUCCESS) { wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Allocate 2 byte to read card's size information. */ if ( (buffer = realloc(buffer, 2)) == NULL) { print_err(ERR_PRFX_NM); perror(""); wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Read card's size, which is stored in byte 1 and 2 of the card. * If 'ret' is not POC_SUCCESS, we will print an error message if a memory * error occured and return. */ if ( (ret = card_read_data(ctn, CARD_SIZE_OFFSET, 2, buffer)) != POC_SUCCESS) { if (ret == POC_MEM_ERR) { print_err(ERR_PRFX_NM); perror(""); } wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Convert the 2 chars to an unsigned short. */ card_size = (buffer[0] << 8) | buffer[1]; /* Read data size, which is stored in byte 3-4 of the card. * If 'ret' is not POC_SUCCESS, we will print an error message if a memory * error occured and return. */ if ( (ret = card_read_data(ctn, DATA_SIZE_OFFSET, 2, buffer)) != POC_SUCCESS) { if (ret == POC_MEM_ERR) { print_err(ERR_PRFX_NM); perror(""); } wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Convert the 2 chars to an unsigned short. */ data_size = (buffer[0] << 8) | buffer[1]; if (data_size != 0) { /* If the card is not empty, we need to read the current data. */ /* Allocate more memory to store card's data. */ if ( (buffer = realloc(buffer, data_size)) == NULL) { print_err(ERR_PRFX_NM); perror(""); wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Read all data. */ if ( (ret = card_read_data(ctn, DATA_AREA_START_OFFSET, data_size, buffer)) != POC_SUCCESS) { if (ret == POC_MEM_ERR) { print_err(ERR_PRFX_NM); perror(""); } wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } } /* Check whether encryption was selected or 'plaintext' instead. */ if (strcmp(card_crypt_ctx->cipher, "plaintext") != 0) { /* Get the encryption key. */ if ((p = getpass(STR_KEY_PROMPT)) == NULL) { wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } strncpy(key, p, 128); /* Save it in 'key'. */ /* Ask user to re-enter the key to avoid typos. */ if (strcmp(key, getpass(STR_RETYPE_NEW_KEY_PROMPT)) != 0) { /* Keys don't match. Return. */ print_err(STR_KEYS_DONT_MATCH); wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* * Call the cipher's key-schedule function, which will expand the key * for the ciphers needs. */ if ( (ret = cipher_setkey(card_crypt_ctx, key, strlen(key))) != POC_SUCCESS) { /* Key-Schedule failed. */ print_err(STR_CIPHER_SETKEY_ERR); wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* If the card is empty, no decryption is needed. */ if (data_size != 0) cipher_ofb(card_crypt_ctx, buffer, data_size); /* Decryption */ /* * After decrypting the data, we will check whether the key was correct. * This is done by checking the buffer for unprintable characters. */ if (check_buffer(buffer, data_size)) { /* Wrong key? Buffer contains garbage. */ printf(STR_WARN_POSSIBLE_WRONG_KEY); if (tolower(getchar()) != 'y') { /* Continue anyway? */ wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } } } /* * Check whether there's enough free space left, to save new password + * description + password_tag(1 byte) + description_tag(1byte) */ if ( (search_free_space(strlen(password) + strlen(description) + TAG_SIZE, buffer, data_size, card_size - 4 - 1)) == -1) { /* The card doesn't have enough free space left... */ print_err(STR_NO_SPACE_LEFT); wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Set offset. For storing new entry. */ position = data_size; /* Allocate more space for new password + description + tags. */ if ( (buffer = realloc(buffer, data_size + strlen(description) + strlen(password) + TAG_SIZE)) == NULL) { print_err(ERR_PRFX_NM); perror(""); wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* * Buffer now contains the memory image of the card plus free space * for our new entry, which consits of the password its description and * two tags. * * Now we will insert the new entry at the end of the image. */ /* DESCRIPTION */ /* First we will store the description tag. */ buffer[position] = DESCRIPTION; /* Now the description. */ memcpy(&buffer[++position], description, strlen(description)); /* Addjust the offset for start writing the password. */ position += strlen(description); /* PASSWORD */ /* First the password tag. */ buffer[position] = PASSWORD; /* ... and finally the password. */ memcpy(&buffer[++position], password, strlen(password)); /* Set new data-size. */ data_size += strlen(description) + strlen(password) + TAG_SIZE; /* * If the user didn't select plaintext "style" for storing passwords, * we will encrypt the buffer before writing it to the card. */ if (strcmp(card_crypt_ctx->cipher, "plaintext") != 0) cipher_ofb(card_crypt_ctx, buffer, data_size); /* Encrypt */ /* First we write the data size information to the card. */ /* We need to swap 'data_size' so we can use a 'u8' (char) pointer later. */ data_size = bswap_16(data_size); if ( (ret = card_write_data(ctn, DATA_SIZE_OFFSET, 2, (u8 *) &data_size)) != POC_SUCCESS) { if (ret == POC_MEM_ERR) { print_err(ERR_PRFX_NM); perror(""); } wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } /* Now the data area will be written to the card. */ if ( (ret = card_write_data(ctn, DATA_AREA_START_OFFSET, bswap_16(data_size), buffer)) != POC_SUCCESS) { if (ret == POC_MEM_ERR) { print_err(ERR_PRFX_NM); perror(""); } wipe_out_data(); card_close_terminal(ctn); return(POC_ERROR); } card_close_terminal(ctn); /* wipe clean */ wipe_out_data(); /* wipe sensetive cipher specific data. */ cipher_wipe(card_crypt_ctx); return(POC_SUCCESS);}/****************************************************************************** * * Function : search_and_remove * * Description : This function remove a password + description entry from the * card's data area. * * Input : [1] description (char) * The description of the password which will be removed. * [2] buffer (u8) * The buffer which contains an image of the card's data * area. * * Return : -1 (error), 'j' (number of removed characters) * *****************************************************************************/static int search_and_remove(const char * const description, u8 * const buffer) { int i = 0, j = 0; /* Counters. */ u8 *ptr; /* Pointer for the data area. */ /* * This loop searches for the entry with the given description * ('description') and removes the entry (password + description). */ while (buffer[i] != '\0') { /* Loop until we've reached the end. */ /* * Every entry of the data area starts with the description followed by * the password. */ if (buffer[i] != DESCRIPTION) /* Did we find a new entry? */ i++; /* Check next byte next time. */ else { /* Got an entry... */ ptr = &buffer[i]; i++; /* Compare both descriptions. */ if (!strncasecmp(description, &ptr[1], strlen(description))) { /* Ok, found the right entry. Now we will overwrite the entry. */ do { j++; *ptr++ = '\0'; } while (*ptr != DESCRIPTION && *ptr != '\0'); /* Stop if we are at the end of the image, or at the beginning of another entry. */ return(j); /* Return number of removed characters. */ } } } return(-1); /* No description matched the given one. */}/****************************************************************************** * * Function : defrag_card * * Description : This function defragments the card's data area. * * Input : [1] buffer (u8) * Image of the card's data area. * [2] old_size (int) * Size of the data area, before an entry has been removed. * [3] freed_space (int) * Size of the removed entry in byte. * * Return : nothing is returned. * *****************************************************************************/static void defrag_card(u8 * const buffer, const int old_size, const int freed_space) { int i; for (i = strlen(buffer); i < old_size; i++) buffer[i] = buffer[i + freed_space]; buffer[i] = '\0'; /* End with a trailing '\0'. */}#undef wipe_out_data/* Clean sensetive data. */#define wipe_out_data() { \ overwrite_buffer(p); \ overwrite_buffer(key); \ overwrite_buffer(buffer); \ drop_mbuffer(buffer); \}/****************************************************************************** * * Function : password_remove * * Description : This function removes a data area entry, which has the * associated description. * * Input : [1] card_crypt_ctx (crypt_context) * Information about data encryption (cipher, security-level) * [2] port (u16) * Com-Port * [3] description (char) * The entrie's description which shall be removed. * * Return : POC_ERROR or POC_SUCCESS *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -