C/C++ 编程代写
当前位置:以往案例 > >C Assembly案例 | C语言汇编案例 | 硬件编程案例
2020-07-12

C Assembly案例 You have been hired to write a crypto program to encipher and decipher data. Your program should read the data to be enciphered from stdin (either from keyboard input or redirected input).

Programming Assignment 2 (PA2) – Cipher



Milestone Due: Wednesday, February 6 @ 11:59 pm

Final Due: Wednesday, February 13 @ 11:59 pm


Assignment Overview Getting Started Example Input Detailed Overview Milestone Functions
Post-Milestone Functions Unit Testing README File Extra Credit Turnin Summary


You have been hired to write a crypto program to encipher and decipher data. Your program should read the data to be enciphered from stdin (either from keyboard input or redirected input). The enciphered data should be written to stdout which could be redirected to a file.

The purpose of this programming assignment is to gain more experience with ARM assembly bit-wise operations, memory loads and stores (ldr/str), and allocating local variables on the runtime stack and accessing them relative to the frame pointer (fp). You will use Standard C Library routines and varied techniques to communicate C Preprocessor-derived values to your assembly routines (accessing global variables set in a C function and calling C functions from assembly).



README: 10 points – See README Requirementshere and questions below
http://cseweb.ucsd.edu/~ricko/CSE30READMEGuidelines.pdf
Compiling: 5 points – Using our Makefile; no warnings. If what you turn in does not compile withthe given Makefile, you will receive 0 points for this assignment. NO EXCEPTIONS!
Style: 20 points – See Style Requirementshere
http://cseweb.ucsd.edu/~ricko/CSE30StyleGuidelines.pdf
● Correctness: 65 points
Milestone (15 points) – To be distributed across the Milestone functions (seebelow)
Make sure you have all files tracked in
Extra Credit: 2 points – View Extra Credit section for more
Wrong Language: You will lose 10 points for each module in the wrong language, C vs. Assemblyor vice
NOTE: If what you turn in does not compile with given Makefile, you will receive 0 points for this assignment.



Follow these steps to acquire the starter files and prepare your Git repository.



Gathering Starter Files:

The first step is to gather all the appropriate files for this assignment. Connect to pi-cluster via ssh.

$ ssh cs30xyz@pi-cluster.ucsd.edu

Create and enter the pa2 working directory.

$ mkdir ~/pa2

$ cd ~/pa2

Copy the starter files from the public directory.

$ cp ~/../public/pa2StarterFiles/* ~/pa2/

Copy your isInBounds files from your pa1 directory.

$ cp ~/pa1/isInBounds.s ~/pa2/

$ cp ~/pa1/testisInBounds.c ~/pa2/





Preparing Git Repository:

You are required to use Git with this and all future programming assignments. Refer to the PA0 writeup for how to set up your local git repository.



The usage for the PA2 cipher program:

Usage: ./pa2 passphrase key0 key1 rotateValue
passphrase (must have length within the range [4, 8])

key0 (must be numeric; decimal, octal, or hexadecimal) key1 (must be numeric; decimal, octal, or hexadecimal) rotateValue (must be a decimal value within the range [+0, +63])



The passphrase is a string whose bytes will be XORed with the bytes of integers key0 and key1. This generates an 8-byte/64-bit mask which will generate a pad used to encrypt a message. We generate the pad by rotating the mask by rotateValue bits for every 8 bytes of the input message. The message is read from stdin (user keyboard input or redirected file).



Example of encryption/decryption
Let’s encrypt something! We will run the executable with:

passphrase =cse30
key0 =0xABCD
key1 =0x1234
rotateValue =8
which looks like this:

cs30xyz@pi-cluster-001:pa2$ ./pa2 cse30 0xABCD 0x1234 8



If run it like this, the executable will appear to stall / loop infinitely. This is because it is waiting for user input to encrypt. We can type in some message we want to encrypt, press enter and Ctrl+D twice (^D) to indicate we are done typing (user inputted text is bolded):



cs30xyz@pi-cluster-001:pa2$ ./pa2 cse30 0xABCD 0x1234 8

meet me in B420 at 20 past 4
^DS��@%CA��@QCUqWy^Dcs30xyz@pi-cluster-001:pa2$

As you can see, we get a random-looking piece of output in return. This is the encrypted message. Though typing directly is an option to encrypt using PA2 cipher, it’s obviously very messy and difficult to use. Below are some ways to streamline the encryption/decryption process.

Assume we have a file called input, which contains the following text: File input





The following command will encrypt the input file and print it out to stdout (terminal screen): cs30xyz@pi-cluster-001:pa2$ ./pa2 cse30 0xABCD 0x1234 8 < input S��@%CA��@QCUqWy

As you can see, the output is still messy and unreadable. On top of this, it is not very easy to copy/paste this output and send it to your desired recipient. What would be better is to capture the output in a file called output:

cs30xyz@pi-cluster-001:pa2$ ./pa2 cse30 0xABCD 0x1234 8 < input > output

Notice the use of the bash redirection operators < and >. Since the input to the executable is read from stdin, we use the < operator to redirect the file input to the stdin file. This makes the contents of input available to the program as if someone were typing directly to stdin. The > operator takes output on stdout and redirects it into a file — in this case we chose the name “output”.

Once your recipient gets your message in some way (e.g. you send them the output file), they can decrypt your message as long as they know the same passphrase, keys, and rotateValue:

cs30xyz@pi-cluster-001:pa2$ ./pa2 cse30 0xABCD 0x1234 8 < output meet me in B420 at 20 past 4

If someone intercepts your file, but doesn’t know the passphrase, keys, or rotateValue, they won’t be able to decrypt the file:

cs30xyz@pi-cluster-001:pa2$ ./pa2 idontkno 123 456 6 < output

grğd6+ ��0�ӭ��S��瘼�b

Notice how the output file has become the input file on the decryption side.



Viewing output files
As noted above, the output of encryption is usually unreadable. However, it can be helpful in debugging to see what bytes (specifically, what byte values) are in the encrypted output. You can cross reference these values with the original message to make sure that the right byte values are coming out of the encryption. To do this, you should use the hexdump command line tool. For example, using hexdump on the output file from above looks like:

cs30xyz@pi-cluster-001:pa2$ hexdump -C output

00000000 0e 16 ab 8a 10 5d 44 71 38 0d 53 8c ca 02 00 01 |…..]Dq8.S…..|
00000010 40 25 43 41 fe de 40 51 43 55 71 57 79 |@%CA..@QCUqWy|
0000001d


Testing with the public executable


A sample stripped executable provided for you to try and compare your output against is available in the public directory. Note that you cannot copy it to your own directory; you can only run it using the following command (where you will also pass in the command line arguments):

$ ~/../public/pa2test

It is suggested that you test your program by encrypting a message using your executable and decrypting with the public executable, or vice versa. If you can do this successfully and retain all the information from the original message, this ensures that your implementation will be compatible with the public executable for testing. It is not enough that your executable can encrypt/decrypt messages generated by itself (think about why).





Example input that has error output:

cs30xyz@pi-cluster-001:pa2$ ./pa2

cs30xyz@pi-cluster-001:pa2$ ./pa2 pass 0xEE 0xFF 0x11 -2 cs30xyz@pi-cluster-001:pa2$ ./pa2 bob 0xA 0xB 0 cs30xyz@pi-cluster-001:pa2$ ./pa2 cse30 xyz 10 42

cs30xyz@pi-cluster-001:pa2$ ./pa2 panama 123 456 0x5

Example input that has normal output. Here, input is a file that you want to encrypt/decrypt: cs30xyz@pi-cluster-001:pa2$ ./pa2 cse30 0x0A0B0C0D 0x01020304 3 < input cs30xyz@pi-cluster-001:pa2$ ./pa2 minty -3 -5 32 < input



The function prototypes for the various C and Assembly functions are as follows.



C routines:

int processKey( char * str, unsigned char key[] );

int processPassphrase( char * str, unsigned char * passphrase );



Assembly routines:

void cipher( FILE * inFile, unsigned char mask[], int rotateValue ); void generateMask( unsigned char keys[], unsigned char passphrase[],

unsigned char mask[] );

int isInBounds( int value, int minBound, int maxBound ); int isOdd( int num );

int processRotateValue( char * str, int * rotateValue ); void rotate( unsigned char mask[], int rotateValue );

void xorBytes( unsigned char originalText[], unsigned char mask[], unsigned char cipherText[], unsigned int numBytes );



For the Milestone, you will need to complete:
processKey.c
xorBytes.s

processRotateValue.s
generateMask.s

rotate.s
isInBounds.s

isOdd.s


Process Overview:
The following is an explanation of the main tasks of the assignment, and how the individual functions work together to form the whole program.

In this program, you will be enciphering and deciphering data by XORing it with a bitmask. This bitmask will be generated by combining two keys and a passphrase together. To make your cipher even stronger, the bitmask will be rotated throughout the enciphering of the message. To decipher the data, just run it through the cipher again. (This cipher runs on XOR, which has which special property?)



Process command linearguments
There are 4 expected user inputs: passphrase, key0, key1, and rotateValue. Within main() in main.c, you will be processing the command line arguments using helper functions, and checking for errors.

Create cryptomask
Use generateMask() to create the crypto mask using the passphrase and keys input as command line arguments.

Encrypt/Decryptdata
Use cipher() to encrypt/decrypt the data from stdin.

C Assembly案例C Assembly案例
Listed below are the modules to be written for the milestone.



isInBounds.s
int isInBounds( int value, int minBound, int maxBound );

Copy over from PA1. No changes necessary.



isOdd.s
int isOdd( int num );



This function will decide if the int passed in is odd or even. You must use a bitwise operation to determine if num is odd or even. No sdiv, no udiv, no helper subroutines. ?

Hint: What makes an int odd/even? How does that get expressed in its bit pattern? Return Value: 1 if num is odd, otherwise return 0.

processKey.c
int processKey( char * str, unsigned char key[] );



This function will be used to process the second and third command line arguments, key0 and key1. This function takes in one string at a time, so you will have to call this function twice, once on each key.

Convert the str passed in to an unsigned int. Notice that the string might represent the int in decimal, octal or hexadecimal. If an error occurred, return the appropriate constant right away (see “Reasonsfor error” section below).
Extract the bytes from the int, storing each byte into the char array key. For example, if the string is “0xAB”, the key array should look like {0x00, 0x00, 0x00, 0xAB}, each byte represented in hexadecimal.


Things to consider:

How can you convert a string to an unsigned int where the value can be expressed in either decimal, octal, or hexadecimal? (hint: man -s3strtoul())
How can you check if errors occurred during theconversion?


Reasons for error:

If the number was too large to be successfully converted, return ERANGE_ERRright away.
If the number contained invalid characters, return ENDPTR_ERRright away.


Return Value: If the conversion was successful, the key is stored in the output parameter (key), and 0 is returned. Otherwise, return the appropriate error value.



processRotateValue.s
int processRotateValue( char * str, int * rotateValue );



This function will convert the rotate value passed in as a command line argument from a string to an int (interpreted as a decimal value), and will check if it is in the required bounds of [MIN_ROTATE, MAX_ROTATE] inclusive (make sure you use your isInBounds() function). Make sure you check for errors in the order listed in “Reasons for error” section below. The processed rotate value will be stored in the output parameter rotateValue and the return value will be used to indicate errors.



Make sure you use the global variables defined in pa2Globals.c. Remember, you need to load these values from their labels before using them in your assembly routine.



Things to consider:

How can you convert a string to an int as a decimalvalue?
How can you check if errors occurred during theconversion?


Reasons for error:

If the number was too large to be successfully converted, return ERANGE_ERRright away.
If the number contained invalid characters, return ENDPTR_ERRright away.
If the number was outside the required bounds, return BOUND_ERRright away.


Return Value: If the conversion was successful, the rotate value is stored in the output parameter (rotateValue), and 0 is returned. Otherwise, return the appropriate error value.



xorBytes.s
void xorBytes( unsigned char originalText[], unsigned char mask[], unsigned char cipherText[], unsigned int numBytes );



Encrypts by XORing a mask over the original plaintext to generate a ciphertext. numBytes is the number of bytes of the originalText that should be encrypted. You should do this in a loop — loading, encrypting, and storing one byte at a time:

cipherText[i] = originalText[i] ^ mask[i];

Store the XORed bytes in the output parameter cipherText.



generateMask.s
void generateMask( unsigned char keys[], unsigned char passphrase[], unsigned char mask[] );



Generates the 64-bit mask used for encryption from keys and passphrase by XORing the bytes of keys with the corresponding bytes of passphrase. Store the XORed bytes in the output parameter mask. Hint: what other milestone function could you delegate to do this?

rotate.s
void rotate( unsigned char mask[], int rotateValue );



This function will rotate the bits in the 64-bit crypto mask. The rotateValue indicates how many bits to rotate by. An odd rotateValue indicates the bits will be rotated left, and an even rotateValue indicates the bits will be rotated right (use your isOdd() function). You should perform the rotation one bit at a time. After performing the rotation, store the rotated mask back into the mask parameter.



For example:

If we rotate the mask using a rotateValue of 2, we will rotate 2 bits to the right since 2 is even. Notice how this is done as two 1-bit rotations to the right.

C assemble案例C assemble案例
The following shows the result of rotating a 64-bit mask by 18 bits: Before rotate: 0x89ABCDEF01234567

After rotate: 0xD159E26AF37BC048



Listed below are the modules to be written after the milestone functions are complete.



processPassphrase.c
int processPassphrase( char * str, unsigned char * passphrase );



Process the passphrase from the command line arguments by checking if str contains at least MIN_PASSPHRASE_SIZE characters and at most MAX_PASSPHRASE_SIZE characters. You should use isInBounds() to help check if the length of str is within the min and max size.

If the length of str is within the bounds:

Copy strover to passphrase, which is an unsigned char array of size MAX_PASSPHRASE_SIZE. Do not copy over the null
Do not use strncpy() to copy str because passphrase is an unsigned char *, and strncpy()expects a (signed) char * (see man strncpy). Therefore you must individually copy over the characters one at a
Donot think of passphrase as a string; passphrase is just an array of
MAX_PASSPHRASE_SIZE bytes of hex values and is NOT null terminated.



If str is shorter than MAX_PASSPHRASE_SIZE chars, add padding to passphrase to fill all MAX_PASSPHRASE_SIZE You will pad the array by copying over str again char by char backwards from the last char. See diagram below for examples.
Say MAX_PASSPHRASE_SIZE is 8 and MIN_PASSPHRASE_SIZE is 4, then:



Reasons for error:

If strhas fewer than MIN_PASSPHRASE_SIZE chars, or more than MAX_PASSPHRASE_SIZE chars, return LENGTH_ERR right away.


Return Value: If an error was encountered, return the appropriate error value. Otherwise, the passphrase is stored in the output parameter (passphrase), and 0 is returned on success.



cipher.s
void cipher( FILE * inFile, unsigned char mask[], int rotateValue );



Reads input from the file inFile, applies the cipher specified by mask and rotateValue, and outputs the result to stdout. You will need a CIPHER_BUFFER_SIZE sized buffer to store input (hint: this will be a local variable, how do you allocate space for it?).



The cipher function will follow this general logic:

Read from inFile, reading CIPHER_BUFFER_SIZEbytes at a time into the buffer using fread.
XOR the buffer contents with the mask, in chunks of 8 bytes (usingxorBytes()).
Rotatethe mask by rotateValue every time after XORing a chunk of 8


If there are any bytes leftover after operating 8 bytes at a time, be sure to XOR the remaining bytesand rotate the mask again. Be careful of cases when your buffer is not entirely filled after reading from file. In these cases you should only operate on the bytes read from the file, not all of the bytes in the
Write the ciphered bytes to stdoutand repeat until all of the bytes have been read in and XORed.


main.c
int main( int argc, char * argv[] );



The main function will drive the rest of the program. It will first perform input checking by processing the command-line arguments and checking for errors. If all inputs are valid, it will call generateMask() and cipher(). Otherwise, it will print the corresponding error message and return. Remember that many of the error strings have format specifiers, so be sure to add the appropriate arguments when printing error messages.



First, disable buffering on stdout with this line of code:

(void) setvbuf( stdout, NULL, _IONBF, 0 );



Second, check that the number of arguments is as expected. If not, print out the usage string (STR_USAGE) to

stderr and return EXIT_FAILURE.



Now you will need to process the command line arguments in the following steps. For all cases, if you encounter an error condition, print the corresponding error message to stderr and return EXIT_FAILURE immediately.

passphrase: You will need to initialize an array of MAX_PASSPHRASE_SIZE unsigned characters. Initialize each byte of the passphrasearray with an easily recognizable hexadecimal value such as
0xA5 (defined as INIT_PASSPHRASE in pa2.h). This will make debugging easier by being able to quickly identify if the passphrase has been correctly set by processPassphrase(). If passphrase is still 0xA5A5A5A5A5A5A5A5 after calling processPassphrase(), then you know there is a problem with your processing routine.

Call processPassphrase() with the corresponding command line argument string and the

passphrase array. Check for the following errors in the order they appear below.



Error How to Handle
processPassphrase() returns
LENGTH_ERR

Use fprintf() to print the STR_ERR_BAD_PASSPHRASE error message.


keys(key0 and key1): You will do this using the processKey() function, operating on one key at a time. Note that even though key0 and key1 are input as separate command line arguments, their bytes derived from processKey() must be joined into a single 8 byte array, with key0’s bytes to the left of key1’s
For example, if the command line arguments for key0 and key1 are 0xAABBCCDD and 0x11223344, then by the end of this processing stage you should have a keys array that looks like:

{ 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22, 0x33, 0x44 }



Process key0 first, then key1. After each call to processKey(), check for the following errors in the order they appear below.



Error How to Handle
processKey() returns ERANGE_ERR Use snprintf() to build the error string using STR_ERR_CONVERTING (make sure the string is null-terminated). Use perror() to print the string, passing the string as a parameter.
Use fprintf() to print a newline after the error message.

processKey() returns ENDPTR_ERR Use fprintf() to print the STR_ERR_NOTINT error message.


rotateValue: Use the processRotateValue() Check for the following errors in the order they appear below.


Error How to Handle
processRotateValue() returns
ERANGE_ERR

Use snprintf() to build the error string using STR_ERR_CONVERTING (make sure the string is null-terminated). Use perror() to print the string, passing the string as a parameter.
Use fprintf() to print a newline after the error message.

processRotateValue() returns
ENDPTR_ERR

Use fprintf() to print the STR_ERR_NOTINT error message.
processRotateValue() returns
BOUND_ERR

Use fprintf() to print the STR_ERR_BAD_ROT error message.


If no error occurred while processing the command line arguments, then proceed with encryption/decryption:

Createthe encryption mask using generateMask() on the passphrase and keys.
Use cipher()to encrypt data from stdin with the mask and rotateValue.


Reasons for error:

Incorrect number of command line arguments are passedin
passphraseis not the right length (within [MIN_PASSPHRASE_SIZE, MAX_PASSPHRASE_SIZE])
key0, key1, or rotateValueare too large to be converted to ints
key0, key1, or rotateValuecontain invalid characters and cannot be converted to ints
rotateValueis not in bounds


Return Value: If errors were encountered, return EXIT_FAILURE. Otherwise, return EXIT_SUCCESS.





You are provided with only one basic unit test file for the Milestone function, isOdd(). This file only has minimal test cases and is only meant to give you an idea of how to write your own unit test files. You must write unit test files for each of the Milestone functions, as well as add several of your own thorough test cases to all of the unit test files. You need to add as many unit tests as necessary to cover all

possible use cases of each function. You will lose points if you don’t do this! You are responsible for



making sure you thoroughly test your functions. Make sure you think about boundary cases, special cases, general cases, extreme limits, error cases, etc. as appropriate for each function. The Makefile includes the rules for compiling these tests. Keep in mind that your unit tests will not build until all required files for that specific unit test have been written. These test files will be collected with the Milestone, they must be complete before you submit your Milestone. Notice that testisInBounds.c is listed, so make sure to topy this file into your pa2 directory.




Unit tests you need to complete: testgenerateMask.c testisInBounds.c (from pa1) testisOdd.c testprocessKey.c testprocessRotateValue.c testrotate.c  testxorBytes.c

To compile:
$ make testisOdd



To run:
$ ./testisOdd



(Replace “testisOdd” with the appropriate file names to compile and run the other unit tests)





We also supply you an extra set of “optimized” Makefile targets for your tester files. These targets will compile your tester file with all optimizations turned on, similar to how your Milestone functions will be compiled for grading. Sometimes you will get (un)lucky where your program appears to work even when there is something wrong (like incorrect memory layout or modifying a register you shouldn’t). Compiling with optimizations will expose some of these hidden problems. Again, this is how the milestone will be tested during grading, so use the optimization targets to try to expose these issues.

However, compiling this way prevents you from using gdb to debug, so make sure to compile the regular way when debugging and try the optimized targets after your tests pass.



To compile with optimizations on:
$ make testisOdd-opt

To run:
$ ./testisOdd-opt



Remember to follow all of the guidelines outlined in the README Guidelines.



Questions to Answer in your README:

[ARM]
Given the arraydefinition
int arr[] = { 4, 3, 2, 1 };

write a single ARM assembly instruction that loads the value of arr[2] and puts it into register r2. Assume that the address of the first element of arr is stored in r3 before your instruction executes.

[Vim]
How do you search for all occurrences of the string “mask”(without the quotes)?
(a) What is the command to open another file called txt(in the same directory) in the current vim session by splitting the window into top and bottom halves? (b) How about splitting into left and right? (c) How do you move between files when in split mode?


(a) What is the command to search and replace all occurrences of “cypher” with “cipher”? (b) Whatis the command to search and replace all occurrences of “cypher” with “cipher” but ask for confirmation first, and (c) what option should you type to confirm substitution of this match?
What is the command to force quit without saving after you made someedits?
(a) What is the command to show tabs and (b) what is the command to turn itoff?
[Unix]
What is the command to open a file txtin Vim and go to a certain line number x? (This is a single command)
(a) What is the command to show lines that contain “int” in the file c? (b) What is the command to show five lines above and below each line that contains “int”in the file processKey.c?
(a) What is the command to change the permissions of the file shsuch that no one can read, write or execute the file? (b) What is a command to check for the file permissions of baz.sh?
[Academic Integrity]
Why is it important for professional engineers to act withintegrity?


There is a maximum of 2 points total for extra credit on this assignment.

Early turnin: [2 Points] 48 hours before regular due date and time [1 Point] 24 hours before regular due date and time (it’s one or the other, notboth)


See the turnin instructions here. Your file names must match the below *exactly* otherwise our Makefile will not find your files.



Milestone Turnin:

Due: Wednesday night, February 6 @ 11:59 pm





Files required for the Milestone:

Files required for the Milestone:

generateMask.s isInBounds.s isOdd.s processKey.c

processRotateValue.s rotate.s

xorBytes.s



testgenerateMask.c testisInBounds.c testisOdd.c testprocessKey.c testprocessRotateValue.c testrotate.c testxorBytes.c



Final Turnin:

Due: Wednesday night, February 13 @ 11:59 pm



If there is anything in these procedures which needs clarifying, please feel free to ask any tutor, the instructor, or post on the Piazza Discussion Board.

在线提交订单