diff options
Diffstat (limited to 'base/native-tools/src/tkstool/file.c')
-rw-r--r-- | base/native-tools/src/tkstool/file.c | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/base/native-tools/src/tkstool/file.c b/base/native-tools/src/tkstool/file.c new file mode 100644 index 000000000..d757225fc --- /dev/null +++ b/base/native-tools/src/tkstool/file.c @@ -0,0 +1,518 @@ +/* --- BEGIN COPYRIGHT BLOCK --- + * 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; version 2 of the License. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 Red Hat, Inc. + * All rights reserved. + * --- END COPYRIGHT BLOCK --- + */ + +#include "tkstool.h" + +SECStatus +TKS_ReadInputFileIntoSECItem( char *input, + char *hexInternalKeyKCV, + int hexInternalKeyKCVLength, + char *wrappedKeyName, + SECItem *wrappedKey ) +{ + char buf[1]; + PRFileDesc *fd = NULL; + PRInt32 c = 0; + PRInt32 k = 0; + PRInt32 count = 0; + PRIntn firstCount = 0; + PRIntn secondCount = 0; + PRIntn thirdCount = 0; + PRIntn i = 0; + SECItem hexWrappedKey = { siBuffer, + NULL, + 0 }; + SECStatus status = SECFailure; + + /* Create a clean new hex display buffer for this wrapped key */ + hexWrappedKey.type = ( SECItemType ) siBuffer; + hexWrappedKey.len = ( ( wrappedKey->len * 2 ) + 1 ); + hexWrappedKey.data = ( unsigned char * ) + PORT_ZAlloc( hexWrappedKey.len ); + if( hexWrappedKey.data == NULL ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* open the input file read-only */ + fd = PR_OpenFile( input, PR_RDONLY, 0666 ); + if( !fd ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* read in the wrapped key */ + while( c < HEX_WRAPPED_KEY_LENGTH ) { + /* read in the next byte */ + count = PR_Read( fd, buf, 1 ); + + /* check for EOF */ + if( count > 0 ) { + /* save acceptable hex characters */ + /* silently throw anything else away */ + switch( *buf ) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + /* acceptable character; save it as typed */ + hexWrappedKey.data[c] = buf[0]; + break; + case 'A': + case 'a': + /* acceptable character; save uppercase version */ + hexWrappedKey.data[c] = 'A'; + break; + case 'B': + case 'b': + /* acceptable character; save uppercase version */ + hexWrappedKey.data[c] = 'B'; + break; + case 'C': + case 'c': + /* acceptable character; save uppercase version */ + hexWrappedKey.data[c] = 'C'; + break; + case 'D': + case 'd': + /* acceptable character; save uppercase version */ + hexWrappedKey.data[c] = 'D'; + break; + case 'E': + case 'e': + /* acceptable character; save uppercase version */ + hexWrappedKey.data[c] = 'E'; + break; + case 'F': + case 'f': + /* acceptable character; save uppercase version */ + hexWrappedKey.data[c] = 'F'; + break; + default: + /* unacceptable character; don't save it */ + continue; + } + + /* increment the number of wrapped key bytes read */ + c++; + } + } + + /* insure that the wrapped key was completely obtained */ + if( c != HEX_WRAPPED_KEY_LENGTH ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* Convert these wrapped key hex digits */ + /* into the data portion of a SECItem */ + TKS_ConvertStringOfHexCharactersIntoBitStream( ( char * ) hexWrappedKey.data, + ( hexWrappedKey.len - 1 ), + wrappedKey->data ); + + /* read in the wrapped key KCV */ + while( k < HEX_WRAPPED_KEY_KCV_LENGTH ) { + count = PR_Read( fd, buf, 1 ); + + if( count > 0 ) { + /* save acceptable hex characters; silently */ + /* throw anything else away */ + switch( *buf ) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + /* acceptable character; save it as typed */ + hexInternalKeyKCV[k] = buf[0]; + break; + case 'A': + case 'a': + /* acceptable character; save uppercase version */ + hexInternalKeyKCV[k] = 'A'; + break; + case 'B': + case 'b': + /* acceptable character; save uppercase version */ + hexInternalKeyKCV[k] = 'B'; + break; + case 'C': + case 'c': + /* acceptable character; save uppercase version */ + hexInternalKeyKCV[k] = 'C'; + break; + case 'D': + case 'd': + /* acceptable character; save uppercase version */ + hexInternalKeyKCV[k] = 'D'; + break; + case 'E': + case 'e': + /* acceptable character; save uppercase version */ + hexInternalKeyKCV[k] = 'E'; + break; + case 'F': + case 'f': + /* acceptable character; save uppercase version */ + hexInternalKeyKCV[k] = 'F'; + break; + default: + /* unacceptable character; don't save it */ + continue; + } + + /* increment the number of key KCV bytes read */ + k++; + } + } + + /* insure that the wrapped key KCV was completely obtained */ + if( k != HEX_WRAPPED_KEY_KCV_LENGTH ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* For convenience, display the read-in wrapped key */ + /* and its associated KCV to the user. */ + if( hexWrappedKey.data != NULL ) { + /* Display this final wrapped key */ + if( ( hexWrappedKey.len - 1 ) != + HEX_WRAPPED_KEY_LENGTH ) { + /* invalid key length */ + PR_fprintf( PR_STDERR, + "ERROR: Invalid data length of %d bytes!\n\n\n", + hexWrappedKey.len ); + status = SECFailure; + goto destroyHexWrappedKey; + } else { + /* Print wrapped data blob */ + PR_fprintf( PR_STDOUT, + "\n wrapped data: " ); + + /* Print first DES_LENGTH bytes */ + if( wrappedKey->len == ( 3 * DES_LENGTH ) ) { + firstCount = ( ( hexWrappedKey.len - 1 ) / 3 ); + } else { + firstCount = ( ( hexWrappedKey.len - 1 ) / 2 ); + } + for( i = 0; i < firstCount; i += 4 ) { + PR_fprintf( PR_STDOUT, + "%c%c%c%c ", + hexWrappedKey.data[i], + hexWrappedKey.data[i + 1], + hexWrappedKey.data[i + 2], + hexWrappedKey.data[i + 3] ); + } + + /* Print appropriate padding length */ + PR_fprintf( PR_STDOUT, "\n " ); + + /* Print second DES_LENGTH bytes */ + secondCount = firstCount * 2; + for( i = firstCount; i < secondCount; i += 4 ) { + PR_fprintf( PR_STDOUT, + "%c%c%c%c ", + hexWrappedKey.data[i], + hexWrappedKey.data[i + 1], + hexWrappedKey.data[i + 2], + hexWrappedKey.data[i + 3] ); + } + + /* print out last 8 bytes of triple-DES keys */ + if( wrappedKey->len == ( 3 * DES_LENGTH ) ) { + /* Print appropriate padding length */ + PR_fprintf( PR_STDOUT, "\n " ); + + /* Print third DES_LENGTH bytes */ + thirdCount = hexWrappedKey.len; + for( i = secondCount; i < thirdCount; i += 4 ) { + PR_fprintf( PR_STDOUT, + "%c%c%c%c ", + hexWrappedKey.data[i], + hexWrappedKey.data[i + 1], + hexWrappedKey.data[i + 2], + hexWrappedKey.data[i + 3] ); + } + } + + /* Print appropriate vertical spacing */ + PR_fprintf( PR_STDOUT, "\n\n\n" ); + } + } + + if( hexInternalKeyKCV != NULL ) { + /* Display this final wrapped key's KCV */ + if( ( hexInternalKeyKCVLength - 1 ) != + HEX_WRAPPED_KEY_KCV_LENGTH ) { + /* invalid key length */ + PR_fprintf( PR_STDERR, + "ERROR: Invalid key KCV length " + "of %d bytes!\n\n\n", + hexInternalKeyKCVLength ); + status = SECFailure; + goto destroyHexWrappedKey; + } else { + PR_fprintf( PR_STDOUT, + " master key KCV: " + "%c%c%c%c %c%c%c%c\n (pre-computed KCV of the " + "master key residing inside the wrapped data)\n\n\n", + hexInternalKeyKCV[0], + hexInternalKeyKCV[1], + hexInternalKeyKCV[2], + hexInternalKeyKCV[3], + hexInternalKeyKCV[4], + hexInternalKeyKCV[5], + hexInternalKeyKCV[6], + hexInternalKeyKCV[7] ); + } + } + + /* close the input file */ + PR_Close( fd ); + + status = SECSuccess; + +destroyHexWrappedKey: + /* Destroy the hex wrapped key */ + if( hexWrappedKey.data != NULL ) { + PORT_ZFree( ( unsigned char * ) + hexWrappedKey.data, + hexWrappedKey.len ); + hexWrappedKey.data = NULL; + hexWrappedKey.len = 0; + } + + return status; +} + + +SECStatus +TKS_WriteSECItemIntoOutputFile( SECItem *wrappedKey, + char *wrappedKeyName, + char *hexInternalKeyKCV, + int hexInternalKeyKCVLength, + char *output ) +{ + PRFileDesc *fd = NULL; + PRInt32 count = 0; + PRInt32 r = 0; + PRIntn firstCount = 0; + PRIntn secondCount = 0; + PRIntn thirdCount = 0; + PRIntn i = 0; + SECItem hexWrappedKey = { siBuffer, + NULL, + 0 }; + SECStatus status = SECFailure; + + /* Create a clean new hex display buffer for this wrapped key */ + hexWrappedKey.type = ( SECItemType ) siBuffer; + hexWrappedKey.len = ( ( wrappedKey->len * 2 ) + 1 ); + hexWrappedKey.data = ( unsigned char * ) + PORT_ZAlloc( hexWrappedKey.len ); + if( hexWrappedKey.data == NULL ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* Convert this wrapped key into hex digits */ + TKS_StringToHex( ( PRUint8 * ) wrappedKey->data, + ( PRIntn ) wrappedKey->len, + ( PRUint8 * ) hexWrappedKey.data, + ( PRIntn ) hexWrappedKey.len ); + + /* For convenience, display this wrapped key to the user. */ + if( hexWrappedKey.data != NULL ) { + /* Display this final wrapped key */ + if( ( hexWrappedKey.len - 1 ) != + HEX_WRAPPED_KEY_LENGTH ) { + /* invalid key length */ + PR_fprintf( PR_STDERR, + "ERROR: Invalid data length of %d bytes!\n\n\n", + hexWrappedKey.len ); + status = SECFailure; + goto destroyHexWrappedKey; + } else { + /* Print wrapped data blob */ + PR_fprintf( PR_STDOUT, + " wrapped data: " ); + + /* Print first DES_LENGTH bytes */ + if( wrappedKey->len == ( 3 * DES_LENGTH ) ) { + firstCount = ( ( hexWrappedKey.len - 1 ) / 3 ); + } else { + firstCount = ( ( hexWrappedKey.len - 1 ) / 2 ); + } + for( i = 0; i < firstCount; i += 4 ) { + PR_fprintf( PR_STDOUT, + "%c%c%c%c ", + hexWrappedKey.data[i], + hexWrappedKey.data[i + 1], + hexWrappedKey.data[i + 2], + hexWrappedKey.data[i + 3] ); + } + + /* Print appropriate padding length */ + PR_fprintf( PR_STDOUT, "\n " ); + + /* Print second DES_LENGTH bytes */ + secondCount = firstCount * 2; + for( i = firstCount; i < secondCount; i += 4 ) { + PR_fprintf( PR_STDOUT, + "%c%c%c%c ", + hexWrappedKey.data[i], + hexWrappedKey.data[i + 1], + hexWrappedKey.data[i + 2], + hexWrappedKey.data[i + 3] ); + } + + /* print out last 8 bytes of triple-DES keys */ + if( wrappedKey->len == ( 3 * DES_LENGTH ) ) { + /* Print appropriate padding length */ + PR_fprintf( PR_STDOUT, "\n " ); + + /* Print third DES_LENGTH bytes */ + thirdCount = hexWrappedKey.len; + for( i = secondCount; i < thirdCount; i += 4 ) { + PR_fprintf( PR_STDOUT, + "%c%c%c%c ", + hexWrappedKey.data[i], + hexWrappedKey.data[i + 1], + hexWrappedKey.data[i + 2], + hexWrappedKey.data[i + 3] ); + } + } + + /* Print appropriate vertical spacing */ + PR_fprintf( PR_STDOUT, "\n\n\n" ); + } + } + + /* For convenience, display this wrapped key's */ + /* master key KCV to the user. */ + if( ( hexInternalKeyKCV != NULL ) && + ( hexInternalKeyKCVLength == HEX_WRAPPED_KEY_KCV_LENGTH ) ) { + /* display this wrapped key's computed KCV value (in hex) */ + PR_fprintf( PR_STDOUT, + " master key KCV: " + "%c%c%c%c %c%c%c%c\n (computed KCV of the " + "master key residing inside the wrapped data)\n\n\n", + hexInternalKeyKCV[0], + hexInternalKeyKCV[1], + hexInternalKeyKCV[2], + hexInternalKeyKCV[3], + hexInternalKeyKCV[4], + hexInternalKeyKCV[5], + hexInternalKeyKCV[6], + hexInternalKeyKCV[7] ); + } + + /* open the output file read-write */ + fd = PR_OpenFile( output, ( PR_RDWR | PR_CREATE_FILE ), 0666 ); + if( !fd ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* write out the wrapped key (in hex) to the output file */ + while( count < HEX_WRAPPED_KEY_LENGTH ) { + /* write out 4 bytes */ + r = PR_Write( fd, &( hexWrappedKey.data[count] ), 4 ); + if( r != 4 ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* increment the byte count by 4 */ + count += 4; + + if( count >= HEX_WRAPPED_KEY_LENGTH ) { + r = PR_Write( fd, "\n", 1 ); + if( r != 1 ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + } else { + r = PR_Write( fd, " ", 1 ); + if( r != 1 ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + } + } + + /* reinitialize count */ + count = 0; + + /* write out the master key KCV (in hex) to the output file */ + while( count < HEX_WRAPPED_KEY_KCV_LENGTH ) { + /* write out 4 bytes */ + r = PR_Write( fd, &( hexInternalKeyKCV[count] ), 4 ); + if( r != 4 ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + + /* increment the byte count by 4 */ + count += 4; + + if( count >= HEX_WRAPPED_KEY_KCV_LENGTH ) { + r = PR_Write( fd, "\n", 1 ); + if( r != 1 ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + } else { + r = PR_Write( fd, " ", 1 ); + if( r != 1 ) { + status = SECFailure; + goto destroyHexWrappedKey; + } + } + } + + /* close the output file */ + PR_Close( fd ); + + status = SECSuccess; + +destroyHexWrappedKey: + /* Destroy the hex wrapped key */ + if( hexWrappedKey.data != NULL ) { + PORT_ZFree( ( unsigned char * ) + hexWrappedKey.data, + hexWrappedKey.len ); + hexWrappedKey.data = NULL; + hexWrappedKey.len = 0; + } + + return status; +} + |