blender/intern/keymaker/key.c
Kent Mein 0fbadc8eb7 Yes I did it again ;)
added the following 3 lines to everything in the intern dir:
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Kent
--
mein@cs.umn.edu
2002-11-25 09:53:07 +00:00

497 lines
13 KiB
C

/**
* $Id$
* ***** BEGIN GPL/BL DUAL LICENSE 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; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
/* ex:ts=4 */
/**
* $Id$
* Copyright (C) 2001 NaN Technologies B.V.
* Blender Key loader library
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "blenkey.h" /* external interface */
#include "key_internal.h"
char *Hexify(byte *in, unsigned int length) {
unsigned int i;
char Tstring[3];
char *out = malloc((2*length + 1) * sizeof(char));
sprintf(out, "%02X", in[0]);
for (i=1; i<length; i++) {
sprintf(Tstring, "%02X", in[i]);
strcat(out, Tstring);
}
return (out);
}
byte *DeHexify(char *in) {
size_t len = strlen(in);
byte *out = malloc((len/2) * sizeof(byte));
unsigned int hexedbyte;
unsigned int i;
char *inp = in;
byte *outp = out;
for (i=0; i<(len/2); i++) {
sscanf(inp, "%2x", &hexedbyte);
inp += 2;
*outp = (byte) hexedbyte;
outp++;
}
/* printf("\nlen=%d, string=[%s]\n", len, Hexify(out, len/2)); */
return (out);
}
int from_hex(char c) {
return (c<'A') ? (c-'0') : (c-'A'+10);
}
/* 5 ReadHex helper functions ------------------------------------------
read one Hex byte (two characters) and skip newlines if necessary */
byte ReadHexByteFp(FILE *fh, int *newlinetracker) {
unsigned char a;
unsigned char a1, a2;
/* read 2 bytes hexcode of ascii data type */
fread(&a1, 1, 1, fh);
fread(&a2, 1, 1, fh);
a = 16 * (from_hex(a1)) + (from_hex(a2));
/*printf("Char[%d] = %02X\n", *newlinetracker, a); */
*newlinetracker += 2;
/* skip the newlines */
if (*newlinetracker == 72) {
fseek(fh, 1, SEEK_CUR);
*newlinetracker = 0;
/*printf("LastChar = %02X\n", a); */
}
return((byte) a);
}
byte ReadHexByteCp(char **from) {
int a;
/* read 2 bytes hexcode of ascii data type */
sscanf(*from, "%2x", &a);
/*printf("Char = %02X\n", a); */
*from += 2;
return((byte) a);
}
/* Generic hex2int */
int HexToInt(int a) {
if (a == 0x20) /* space, count as 0 ;-) */
return 0;
else
return(a - '0');
}
/* Note: this is only to be used for the header type */
int HexToIntFp(FILE *fh, int *newlinetracker) {
byte a = ReadHexByteFp(fh, newlinetracker);
if (DEBUG) printf("%02X = %d\n", a, a); /* note: no HexToInt here */
return(a);
}
int HexToIntCp(char **from) {
byte a = ReadHexByteCp(from);
if (DEBUG) printf("%02X = %d\n", a, a); /* note: no HexToInt here */
return(a);
}
/* Note: this is only to be used for the header length */
int Hex5ToInt(byte a, byte b, byte c, byte d, byte e) {
return(HexToInt((int) a) * 10000 +
HexToInt((int) b) * 1000 +
HexToInt((int) c) * 100 +
HexToInt((int) d) * 10 +
HexToInt((int) e));
}
/* Note: this is only to be used for the header length */
int Hex5ToIntFp(FILE *fh, int *newlinetracker) {
byte a = ReadHexByteFp(fh, newlinetracker),
b = ReadHexByteFp(fh, newlinetracker),
c = ReadHexByteFp(fh, newlinetracker),
d = ReadHexByteFp(fh, newlinetracker),
e = ReadHexByteFp(fh, newlinetracker);
if (DEBUG) printf("\n%02X%02X%02X%02X%02X = %d\n", a, b, c, d, e,
Hex5ToInt(a, b, c, d, e));
return(Hex5ToInt(a, b, c, d, e));
}
int Hex5ToIntCp(char **from) {
byte a = ReadHexByteCp(from),
b = ReadHexByteCp(from),
c = ReadHexByteCp(from),
d = ReadHexByteCp(from),
e = ReadHexByteCp(from);
if (DEBUG) printf("\n%02X%02X%02X%02X%02X = %d\n", a, b, c, d, e,
Hex5ToInt(a, b, c, d, e));
return(Hex5ToInt(a, b, c, d, e));
}
/* --------------------------------------------------------------------- */
/* return the biggest */
byte checkfunc0(byte a, byte b) {
if (a > b) return a;
else return b;
}
/* return |a-b| */
byte checkfunc1(byte a, byte b) {
if (a > b) return a - b;
else return b - a;
}
/* return the sum mod 256 */
byte checkfunc2(byte a, byte b) {
return ((a + b) % 256);
}
/* return the multiplication mod 256 */
byte checkfunc3(byte a, byte b) {
return ((a * b) % 256);
}
/* return a/b or 0 */
byte checkfunc4(byte a, byte b) {
if (b != 0) return (a / b);
else return 0;
}
char *scan_ascii(FILE *fh, UserStruct *User) {
long ascii_size;
char *ascii_data = NULL;
char *mdhex = NULL;
byte md[RIPEMD160_DIGEST_LENGTH];
char string[1024];
char dosnewlines = 0;
int lines = 0;
int oldftell;
/* NOTE: fscanf is notorious for its buffer overflows. This must be
fixed some day, consider this a proof-of-concept version. */
fscanf(fh, "%1000[^\n]", string);
sscanf(string, "%*s %s %s %lu %d %d %d",
User->email,
User->shopid,
&User->reldate,
&User->keytype,
&User->keylevel,
&User->keyformat);
if (User->keyformat <= BLENKEYFORMAT) {
if (DEBUG) printf(
"Email:[%s] ShopID:[%s] RelDate:[%lu] KeyType[%d] KeyLevel[%d]\n",
User->email, User->shopid, User->reldate, User->keytype,
User->keylevel);
/* read /n/n
check if we're reading dow newlines...
*/
oldftell = ftell(fh);
getc(fh);
if ((ftell(fh) - oldftell) == 2) {
/* yes ! */
dosnewlines = 1;
}
getc(fh);
fscanf(fh, "%1000[^\n]", string);
strncpy(User->name, string, sizeof(User->name) - 1);
if (DEBUG) printf("Name:[%s]\n", User->name);
getc(fh);
/* 4 lines read uptil now... */
lines = 4;
while (getc(fh) != EOF) {
fscanf(fh, "%1000[^\n]", string);
lines++;
/* if (DEBUG) printf("%s\n", string); */
if (strcmp(string, BLENKEYSEPERATOR) == 0) {
getc(fh);
break;
}
}
/* fh now points at the start of the datablock */
ascii_size = ftell(fh);
if (dosnewlines) {
/* if we were reading on dos
ftell will also count the ^M 's in the file;
substract them
*/
ascii_size -= lines;
}
ascii_data = malloc((ascii_size+1) * sizeof(char));
fseek(fh, 0, SEEK_SET);
fread(ascii_data, sizeof(char), ascii_size, fh);
ascii_data[ascii_size] = '\0';
if (DEBUG)
printf("asciiblock is %ld bytes long:\n[%s]\n", ascii_size, ascii_data);
/* calculate the hash checksum */
RIPEMD160(ascii_data, ascii_size, md);
free(ascii_data);
mdhex = Hexify(md, RIPEMD160_DIGEST_LENGTH);
}
return(mdhex);
}
char *ReadHexCryptedData(FILE *fh, int *newlinetracker) {
int HexCryptedDataLength = Hex5ToIntFp(fh, newlinetracker);
int DataType = HexToIntFp(fh, newlinetracker);
char *HexCryptedData = malloc((HexCryptedDataLength+1) * sizeof(char));
int i;
if (DataType != 1) {
/* printf("Error: unexpected datatype for HexCryptedData\n"); */
free(HexCryptedData);
HexCryptedData = 0;
} else {
for (i=0; i<(HexCryptedDataLength/2); i++) {
sprintf(HexCryptedData+2*i, "%02X", ReadHexByteFp(fh, newlinetracker));
}
}
return(HexCryptedData);
}
char *ReadHexCryptedKey(FILE *fh, int *newlinetracker) {
int HexCryptedKeyLength = Hex5ToIntFp(fh, newlinetracker);
int DataType = HexToIntFp(fh, newlinetracker);
char *HexCryptedKey = malloc((HexCryptedKeyLength+1) * sizeof(char));
int i;
if (DataType != 2) {
/* printf("Error: unexpected datatype for HexCryptedKey\n"); */
free(HexCryptedKey);
HexCryptedKey = 0;
} else {
for (i=0; i<(HexCryptedKeyLength/2); i++) {
sprintf(HexCryptedKey+2*i, "%02X", ReadHexByteFp(fh, newlinetracker));
}
}
return(HexCryptedKey);
}
/* NOTE: CHANGE THIS INTO A KEY OF OUR OWN */
void LoadRSApubKey(RSA *Pub) {
static unsigned char n[] =
"\xD1\x12\x0C\x6A\x34\x0A\xCF\x4C\x6B\x34\xA9\x3C\xDD\x1A\x2A\x68"
"\x34\xE5\xB4\xA2\x08\xE8\x9F\xCE\x76\xEF\x4B\x92\x9B\x99\xB4\x57"
"\x72\x95\x78\x1D\x9E\x21\x1B\xF9\x5C\x1B\x0E\xC9\xD0\x89\x75\x28"
"\x08\x13\x6A\xD8\xA9\xC2\xA4\x31\x91\x53\x5A\xB9\x26\x71\x8C\x05";
static unsigned char e[] =
"\x01\x00\x01";
/*
static unsigned char e[] = "\x11";
static unsigned char n[] =
"\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
"\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
"\xAD\xB3\x00\xA0\x28\x5E\x53\x01\x93\x0E\x0C\x70\xFB\x68\x76\x93"
"\x9C\xE6\x16\xCE\x62\x4A\x11\xE0\x08\x6D\x34\x1E\xBC\xAC\xA0\xA1"
"\xF5";
*/
Pub->e = BN_bin2bn(e, sizeof(e)-1, Pub->e);
Pub->n = BN_bin2bn(n, sizeof(n)-1, Pub->n);
}
byte *RSADecryptKey(char *HexCryptedKey) {
byte *CryptedKey = NULL;
byte *Key = NULL;
int KeyLen;
int CryptedKeyLen = strlen(HexCryptedKey)/2;
RSA *Pub = NULL;
/* Load RSA public key */
Pub = RSA_new();
if (Pub == NULL) {
/* printf("Error in RSA_new\n"); */
} else {
LoadRSApubKey(Pub);
Key = malloc(RSA_size(Pub) * sizeof(byte));
CryptedKey = DeHexify(HexCryptedKey);
KeyLen = RSA_public_decrypt(CryptedKeyLen, CryptedKey, Key, Pub,
RSA_PKCS1_PADDING);
if (DEBUG)
printf("CryptedKeyLen = %d, KeyLen = %d\n", CryptedKeyLen, KeyLen);
if (KeyLen == -1) {
#ifndef NDEBUG
printf("Error in RSA_public_decrypt: %s\n", ERR_error_string(ERR_get_error(), NULL));
#endif
free(Key);
Key = NULL;
}
}
return (Key);
}
char *DeCryptDatablock(byte *CryptKey, int keylen, char *HexCryptedData) {
RC4_KEY key;
byte *CryptedData = DeHexify(HexCryptedData);
unsigned int datalen = strlen(HexCryptedData)/2;
char *KeyDataString = malloc(datalen * sizeof(char));
RC4_set_key(&key, keylen, CryptKey);
RC4(&key, datalen, CryptedData, KeyDataString);
free(CryptedData);
return(KeyDataString);
}
char *get_from_datablock(char **DataPtr, char *TypeString) {
int tstringsize = Hex5ToIntCp(DataPtr);
int tstringtype = HexToIntCp(DataPtr);
char *HexString = NULL;
if (atoi(TypeString) != tstringtype) {
/* printf("Unexpected type %d, expected %s\n", tstringtype, TypeString); */
} else {
HexString = malloc((tstringsize+1) * sizeof(char));
strncpy(HexString, *DataPtr, tstringsize);
*DataPtr += tstringsize;
HexString[tstringsize] = '\0';
}
return(HexString);
}
int ReadKeyFile(char *filename, UserStruct *User,
char **Priv, char **Pub, byte **Byte, char **Python) {
FILE *rawkeyfile;
char *HexAsciiHash = NULL, *HexCryptedData = NULL, *HexCryptedKey =
NULL;
int newlinetracker = 0; /* line position, counts from 0-71 */
byte *CryptKey = NULL;
char *KeyDataString = NULL;
char *KeyDataPtr = NULL;
char *HexByte = NULL;
char *mdhex = NULL;
int ret_val = 1;
if ((rawkeyfile = fopen(filename, "rb")) == NULL) {
/* printf("error, cannot read %s\n", filename); */
} else {
/* Scan and interpret the ASCII part */
HexAsciiHash = scan_ascii(rawkeyfile, User);
if (DEBUG) printf("\nHexHash: %s\n", HexAsciiHash);
/* Read the HexCryptedData */
HexCryptedData = ReadHexCryptedData(rawkeyfile, &newlinetracker);
if (DEBUG) printf("\nHexCryptedData: %s\n", HexCryptedData);
/* Read the HexCryptedKey */
HexCryptedKey = ReadHexCryptedKey(rawkeyfile, &newlinetracker);
if (DEBUG) printf("\nHexCryptedKey: %s\n", HexCryptedKey);
/* close keyfile */
fclose(rawkeyfile);
if (HexAsciiHash && HexCryptedKey && HexCryptedData) {
/* Decrypt HexCryptedKey */
CryptKey = RSADecryptKey(HexCryptedKey);
if (CryptKey) {
/* Decrypt HexCryptedData */
KeyDataString = DeCryptDatablock(CryptKey, 16, HexCryptedData);
free(CryptKey);
CryptKey = NULL;
if (KeyDataString) {
if (DEBUG) printf("\nKeyDataString: %s\n", KeyDataString);
/* Extract data from KeyDataString */
KeyDataPtr = KeyDataString;
mdhex = get_from_datablock(&KeyDataPtr, "01");
*Priv = get_from_datablock(&KeyDataPtr, "02");
*Pub = get_from_datablock(&KeyDataPtr, "03");
HexByte = get_from_datablock(&KeyDataPtr, "04");
if (HexByte) {
*Byte = DeHexify(HexByte);
free(HexByte);
HexByte = NULL;
*Python = get_from_datablock(&KeyDataPtr, "05");
/* Check ascii hash */
if (strcmp(mdhex, HexAsciiHash) != 0) {
/* printf("Ascii part checksums do not match !\n");
printf("found: %s\n", mdhex);
printf("check: %s\n", HexAsciiHash);
*/
ret_val = 2;
} else {
if (DEBUG) printf("\nThe ascii part checksum matches\n");
/* everything ok ! */
ret_val = 0;
}
free(mdhex);
mdhex = NULL;
}
free(KeyDataString);
KeyDataString = NULL;
}
}
}
/* cleanup */
if (HexAsciiHash) {
free(HexAsciiHash);
HexAsciiHash = NULL;
}
if (HexCryptedKey) {
free(HexCryptedKey);
HexCryptedKey = NULL;
}
if (HexCryptedData) {
free(HexCryptedData);
HexCryptedData = NULL;
}
}
return (ret_val);
}