void WiiSave::writeCerts(Uint32 filesSize, Uint32 ngId, Uint8* ngPriv, Uint8* ngSig, Uint32 ngKeyId) { Uint8 sig[0x40]; Uint8 ngCert[0x180]; Uint8 apCert[0x180]; Uint8* hash; Uint8 apPriv[30]; Uint8 apSig[60]; char signer[64]; char name[64]; Uint8* data; Uint32 dataSize; sprintf(signer, "Root-CA00000001-MS00000002"); sprintf(name, "NG%08x", ngId); make_ec_cert(ngCert, ngSig, signer, name, ngPriv, ngKeyId); memset(apPriv, 0, 30); apPriv[10] = 1; memset(apSig, 81, 30); sprintf(signer, "Root-CA00000001-MS00000002-NG%08x", ngId); sprintf(name, "AP%08x%08x", 1, 2); make_ec_cert(apCert, apSig, signer, name, apPriv, 0); hash = getSha1(apCert + 0x80, 0x100); generate_ecdsa(apSig, apSig+30, ngPriv, hash); make_ec_cert(apCert, apSig, signer, name, apPriv, 0); delete[] hash; dataSize = filesSize + 0x80; data = new Uint8[dataSize]; Uint8* rawData = m_writer->data(); memcpy(data, rawData + 0xF0C0, dataSize); hash = getSha1(data, dataSize); Uint8* hash2 = getSha1(hash, 20); delete[] hash; delete[] data; generate_ecdsa(sig, sig+30, apPriv, hash2); int stuff = 0x2f536969; if (!isSystemBigEndian()) stuff = swap32(stuff); *(Uint32*)(sig+60) = stuff; delete[] hash2; m_writer->writeBytes((Int8*)sig, 0x40); m_writer->writeBytes((Int8*)ngCert, 0x180); m_writer->writeBytes((Int8*)apCert, 0x180); }
void WiiSave::readCerts(Uint32 totalSize) { Uint32 dataSize = totalSize - 0x340; Uint8* sig = (Uint8*)m_reader->readBytes(0x40); Uint8* ngCert = (Uint8*)m_reader->readBytes(0x180); Uint8* apCert = (Uint8*)m_reader->readBytes(0x180); m_reader->seek(0xF0C0, Stream::Beginning); Uint8* data = (Uint8*)m_reader->readBytes(dataSize); Uint8* hash; hash = getSha1(data, dataSize); Uint8* hash2 = getSha1(hash, 20); check_ec(ngCert, apCert, sig, hash2); }
int main (int argc, char *argv[]) { int sockfd; //socket file descriptor int length; //length of address (of to) int err; //return value of bind for error handling struct sockaddr_in to, from; //addresses for receiving and transmitting socklen_t fromlen; //length of source address struct unsigned char headerstate; //for parsing the id of each package char buff[BUFFERSIZE]; //mesage buffer unsigned short filenamelength; //length of file name char *filename; //name of file unsigned int filelength; //length of file in bytes unsigned long receivedBytes; //Number of received data files (excluding header of each package!) struct stat folderstat = {0}; // to check if received folder exists char filepath[MAXPATHLENGTH]; //path to file in received folder with file name FILE* file; //File stream to write file into unsigned long seqNr; //number of packet received in data transmission unsigned long readSeqNr; //sequence number transmitted by sender char *filebuffer; //holds the file content to write on file char *shaBuffer; //holds the complete file payload accross all data packages char *shaPtr; //for convenience, points to the next character to be written in shaBuffer char *shaVal; //for the actual sha1-value char *recShaVal; //received Sha1-Val char sha1_CMP; //result of comparing sha-values according to task int i; struct timeval timeout; /****** CHECK INPUT ********/ //error handling: argument parsing if (argc != 2) { printf("Illegal Arguments: [RECEIVER_PORT]"); exit(1); } /******** SOCKET CREATION ***********/ // AF_INET --> Protocol Family // SOCK_DGRAM --> Socket Type (UDP) // 0 --> Protocol Field of the IP-Header (0, TCP and UDP gets entered automatically) sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { printf("Socket-Error"); exit(1); } length = sizeof(to); // Clearing bzero(&to, length); //CREATE TARGET ADDRESS // Assign Protocol Family to.sin_family = AF_INET; // Assign Port to.sin_port = htons(atoi(argv[1])); to.sin_addr.s_addr = inet_addr("127.0.0.1"); //bind socket to prepare receiving err = bind(sockfd, (struct sockaddr *) &to, length); if (err < 0) { printf("Binding-Error"); exit(1); } // Length of the Source Address Structure fromlen = sizeof(struct sockaddr_in); /****** RECEIVE HEAD *******/ timeout.tv_sec = WAIT; timeout.tv_usec = 0; // Set socket options for a possible timeout setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); if ((err = recvfrom(sockfd, buff, BUFFERSIZE, 0, (struct sockaddr *)&from, &fromlen)) < 0) { printf(timeout_error); exit(1); } //check if valid package received headerstate = (unsigned char) buff[0]; if(headerstate != HEADER_T) { printf(packet_error); exit(1); } //go and parse the header parseHeader(buff, &filenamelength, &filename, &filelength); //print some parsed info from the header printf(filename_str, filename); printf(filesize_str,filelength); /******* OPEN FILE OPERATIONS *******/ //prepare Sha buffer. Will hold complete file so we can create sha1-value later shaBuffer = calloc(filelength,1); if(!shaBuffer) { printf("Could not allocate shaBuffer\n"); return 1; } //this will be used to iterate on the shaBuffer shaPtr = shaBuffer; printf("Preparing file for writing...\n"); //filename should not exceed limits. If it is too long there could be bufferoverflow, security issues, ... if(strlen(filename) + 10 > MAXPATHLENGTH) { printf("Can not create path: file name too long"); return 1; } //get file path snprintf(filepath, MAXPATHLENGTH, "%s%s", "received/", filename); //check if folder exists, create if it doesn't. Node: needs sudo-rights. if (!( stat("/received", &folderstat) == 0) && (S_ISDIR(folderstat.st_mode)) ){ if (0!= mkdir("/received", 0700)) { printf("error when creating directory\n"); perror("mkdir"); return 1; } } //Open file, handle errors printf("Open file path %s\n", filepath); file = fopen(filepath, "w"); if(!file) { printf("Illegal File"); return 1; } /******* READ FILE TRANSMISSION *********/ //initialise sequence number and number of received bytes seqNr = 0; receivedBytes = 0; printf("Standing by for incoming file...\n"); /* start receiving and interpreting transmission * wait for each data package to be received, then parse it. * Check sequence number against received sequence number. * To properly read the actually received data of the file * write it into the shaBuffer. Once that is filled write the whole * shaBuffer to the hard drive. */ do { err = recvfrom(sockfd, buff, BUFFERSIZE, 0, (struct sockaddr *)&from, &fromlen); //read header state headerstate = (unsigned char) buff[0]; if(headerstate != DATA_T) { printf(packet_error); printf("Wrong Headerstate in file transfer\n"); exit(1); } //read sequence number readSeqNr = (unsigned long) ( ( (unsigned char)buff[1] ) | ( ((unsigned char)buff[2]) << 8 ) | ( ((unsigned char)buff[3]) << 16 ) | ( ((unsigned char)buff[4]) << 24 ) ); if(seqNr != readSeqNr) { printf(order_error, readSeqNr, seqNr); return 1; } //set filebuffer to where the real buffer starts filebuffer = buff+5; for(i = 0; i<err-5; i++) { *(shaPtr++) = filebuffer[i]; } printf("Received %d payload bytes in packet %lu, writing now\n",err-5, seqNr); seqNr++; receivedBytes += err - 5; //received bytes must only store the number of bytes belonging to the data, not the head of the package }while(receivedBytes != filelength); //once we have received everything we're done //write current package to hard drive. fwrite(shaBuffer, 1, filelength, file); printf("File written on drive.\n"); /******* RECEIVE SHA-1 ********/ //receive sha-1 err = recvfrom(sockfd, buff, BUFFERSIZE, 0, (struct sockaddr *)&from, &fromlen); if(err != SHA_DIGEST_LENGTH*2+1 ) { printf(SHA1_ERROR); printf("Wrong Sha-Package length\n"); return 1; } //receive header headerstate = (unsigned char) buff[0]; if(headerstate != SHA1_T) { printf(packet_error); printf("Wrong ID\n"); exit(1); } recShaVal = calloc(SHA_DIGEST_LENGTH*2+1,1); if(!recShaVal) { printf("Could not allocate recShaVal space\n"); return 1; } //parse Sha-value for(i = 1; i < SHA_DIGEST_LENGTH*2+1; i++) { recShaVal[i-1] = (unsigned char)buff[i]; } recShaVal[SHA_DIGEST_LENGTH*2] = '\0'; //calculate sha over received file shaVal = getSha1(shaBuffer, filelength); printf(receiver_sha1, shaVal); //compare results if(strcmp(shaVal, recShaVal) != 0 ) { printf(SHA1_ERROR); sha1_CMP = SHA1_CMP_ERROR; } else { printf(SHA1_OK); sha1_CMP = SHA1_CMP_OK; } /******* SEND SHA COMPARE RESULT ******/ //prepare id buff[0] = SHA1_CMP_T; //prepare compare result buff[1] = sha1_CMP; //and away! err = sendto(sockfd, buff, 2, 0, (struct sockaddr *)&from,fromlen); if (err < 0) { printf("sendto-Error"); exit(1); } /******* CLEAN UP ******/ // Close Socket close(sockfd); fclose(file); free(filename); free(shaBuffer); free(recShaVal); free(shaVal); return 0; }