Initial revision
This commit is contained in:
394
source/blender/decrypt/intern/BLO_decrypt.c
Normal file
394
source/blender/decrypt/intern/BLO_decrypt.c
Normal file
@@ -0,0 +1,394 @@
|
||||
/**
|
||||
* $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 *****
|
||||
* openssl decryption wrapper library
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "openssl/rsa.h"
|
||||
#include "openssl/rc4.h"
|
||||
#include "openssl/err.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include "GEN_messaging.h"
|
||||
|
||||
#include "blenkey.h"
|
||||
#include "BLO_getPubKey.h" // real and stub implemented at writestream ...
|
||||
|
||||
#include "BLO_readStreamGlue.h"
|
||||
#include "BLO_decrypt.h"
|
||||
#include "BLO_en_de_cryptHeader.h"
|
||||
|
||||
struct decryptStructType {
|
||||
struct readStreamGlueStruct *streamGlue;
|
||||
unsigned int streamDone;
|
||||
unsigned char *deCryptKey;
|
||||
int deCryptKeyLen; // NOTE: signed int
|
||||
unsigned char headerbuffer[EN_DE_CRYPTHEADERSTRUCTSIZE];
|
||||
uint32_t datacrc; // crypted data checksum
|
||||
struct BLO_en_de_cryptHeaderStruct *streamHeader;
|
||||
RC4_KEY rc4_key;
|
||||
void *endControl;
|
||||
};
|
||||
|
||||
BLO_decryptStructHandle
|
||||
BLO_decrypt_begin(
|
||||
void *endControl)
|
||||
{
|
||||
struct decryptStructType *control;
|
||||
control = malloc(sizeof(struct decryptStructType));
|
||||
if (!control) return NULL;
|
||||
|
||||
control->streamGlue = NULL;
|
||||
control->streamDone = 0;
|
||||
control->deCryptKey = NULL;
|
||||
control->deCryptKeyLen = 0;
|
||||
strcpy(control->headerbuffer, "");
|
||||
control->datacrc = 0;
|
||||
|
||||
control->streamHeader = malloc(EN_DE_CRYPTHEADERSTRUCTSIZE);
|
||||
if (!control->streamHeader) {
|
||||
free(control);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
control->streamHeader->magic = 0;
|
||||
control->streamHeader->length = 0;
|
||||
strcpy(control->streamHeader->pubKey, "");
|
||||
control->streamHeader->pubKeyLen = 0;
|
||||
strcpy(control->streamHeader->cryptedKey, "");
|
||||
control->streamHeader->cryptedKeyLen = 0;
|
||||
control->streamHeader->datacrc = 0;
|
||||
control->streamHeader->headercrc = 0;
|
||||
control->endControl = endControl;
|
||||
|
||||
return((BLO_decryptStructHandle) control);
|
||||
}
|
||||
|
||||
int
|
||||
BLO_decrypt_process(
|
||||
BLO_decryptStructHandle BLO_decryptHandle,
|
||||
unsigned char *data,
|
||||
unsigned int dataIn)
|
||||
{
|
||||
int err = 0;
|
||||
struct decryptStructType *BLO_decrypt =
|
||||
(struct decryptStructType *) BLO_decryptHandle;
|
||||
|
||||
if (!BLO_decrypt) {
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* First check if we have our header filled in yet */
|
||||
if (BLO_decrypt->streamHeader->cryptedKeyLen == 0) {
|
||||
unsigned int processed;
|
||||
if (dataIn == 0) return err; /* really need data to do anything */
|
||||
processed = ((dataIn + BLO_decrypt->streamDone) <=
|
||||
EN_DE_CRYPTHEADERSTRUCTSIZE)
|
||||
? dataIn : EN_DE_CRYPTHEADERSTRUCTSIZE;
|
||||
memcpy(BLO_decrypt->headerbuffer + BLO_decrypt->streamDone,
|
||||
data, processed);
|
||||
BLO_decrypt->streamDone += processed;
|
||||
dataIn -= processed;
|
||||
data += processed;
|
||||
if (BLO_decrypt->streamDone == EN_DE_CRYPTHEADERSTRUCTSIZE) {
|
||||
/* we have the whole header, absorb it */
|
||||
struct BLO_en_de_cryptHeaderStruct *header;
|
||||
uint32_t crc;
|
||||
//static unsigned char rsa_e[] = "\x11";
|
||||
static unsigned char rsa_e[] = "\x01\x00\x01";
|
||||
RSA *rsa = NULL;
|
||||
byte *publisherPubKey;
|
||||
int publisherPubKeyLen;
|
||||
|
||||
header = (struct BLO_en_de_cryptHeaderStruct *)
|
||||
BLO_decrypt->headerbuffer;
|
||||
crc = crc32(0L, (const Bytef *) header,
|
||||
EN_DE_CRYPTHEADERSTRUCTSIZE - 4);
|
||||
|
||||
if (header->magic == 'A') {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"BLO_en_de_cryptHeaderStruct Magic confirmed\n");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"ERROR BLO_en_de_cryptHeaderStruct Magic NOT confirmed\n");
|
||||
#endif
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_MAGIC);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (crc == ntohl(header->headercrc)) {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"BLO_en_de_cryptHeader CRC correct\n");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"ERROR BLO_en_de_cryptHeader CRC NOT correct\n");
|
||||
#endif
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_CRCHEADER);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
}
|
||||
BLO_decrypt->streamHeader->length = ntohl(header->length);
|
||||
BLO_decrypt->streamHeader->pubKeyLen = ntohl(header->pubKeyLen);
|
||||
memcpy(BLO_decrypt->streamHeader->pubKey, header->pubKey,
|
||||
BLO_decrypt->streamHeader->pubKeyLen);
|
||||
|
||||
// case Publisher: get the .BPkey public key
|
||||
// case Player/Plugin: simply use the data stream public key
|
||||
err = getPubKey(BLO_decrypt->streamHeader->pubKey,
|
||||
BLO_decrypt->streamHeader->pubKeyLen,
|
||||
&publisherPubKey,
|
||||
&publisherPubKeyLen);
|
||||
switch (err) {
|
||||
case 0:
|
||||
// everything OK
|
||||
break;
|
||||
case 1:
|
||||
// publisher without a key
|
||||
case 2:
|
||||
// publishers keylen !=
|
||||
case 3:
|
||||
// publishers key !=
|
||||
default:
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"ALERT users-pubKey != datastream-pubKey, stop reading\n");
|
||||
#endif
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETSPECERR(BRS_NOTOURPUBKEY);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
|
||||
BLO_decrypt->streamHeader->cryptedKeyLen =
|
||||
ntohl(header->cryptedKeyLen);
|
||||
memcpy(BLO_decrypt->streamHeader->cryptedKey,
|
||||
header->cryptedKey,
|
||||
BLO_decrypt->streamHeader->cryptedKeyLen);
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"BLO_decrypt_process gets %u bytes\n",
|
||||
(unsigned int) BLO_decrypt->streamHeader->length);
|
||||
#endif
|
||||
BLO_decrypt->streamHeader->datacrc = ntohl(header->datacrc);
|
||||
|
||||
// finished absorbing and testing the header, create rsa key from it
|
||||
rsa = RSA_new();
|
||||
if (rsa == NULL) {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"Error in RSA_new\n");
|
||||
#endif
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETSPECERR(BRS_RSANEWERROR);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
}
|
||||
// static exponent
|
||||
rsa->e = BN_bin2bn(rsa_e, sizeof(rsa_e)-1, rsa->e);
|
||||
|
||||
// public part into rsa->n
|
||||
rsa->n = BN_bin2bn(publisherPubKey,
|
||||
publisherPubKeyLen,
|
||||
rsa->n);
|
||||
|
||||
//DEBUG RSA_print_fp(stdout, rsa, 0);
|
||||
|
||||
BLO_decrypt->deCryptKey = malloc(RSA_size(rsa) *
|
||||
sizeof(unsigned char));
|
||||
if (! BLO_decrypt->deCryptKey) {
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_MALLOC);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
RSA_free(rsa);
|
||||
return err;
|
||||
}
|
||||
|
||||
// decrypt the cryptkey
|
||||
BLO_decrypt->deCryptKeyLen = RSA_public_decrypt(
|
||||
BLO_decrypt->streamHeader->cryptedKeyLen,
|
||||
BLO_decrypt->streamHeader->cryptedKey,
|
||||
BLO_decrypt->deCryptKey,
|
||||
rsa, RSA_PKCS1_PADDING);
|
||||
if (BLO_decrypt->deCryptKeyLen == -1) {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream,
|
||||
"Error in RSA_public_decrypt %s\n",
|
||||
ERR_error_string(ERR_get_error(),
|
||||
NULL));
|
||||
#endif
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETSPECERR(BRS_DECRYPTERROR);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
RSA_free(rsa);
|
||||
return err;
|
||||
}
|
||||
|
||||
// Finally set the RC4 deCryptKey
|
||||
RC4_set_key(&(BLO_decrypt->rc4_key),
|
||||
BLO_decrypt->deCryptKeyLen,
|
||||
BLO_decrypt->deCryptKey);
|
||||
|
||||
RSA_free(rsa);
|
||||
}
|
||||
}
|
||||
|
||||
/* Is there really (still) new data available ? */
|
||||
if (dataIn > 0) {
|
||||
unsigned char *deCryptBuf = malloc(dataIn);
|
||||
if (! deCryptBuf) {
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_MALLOC);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
}
|
||||
|
||||
BLO_decrypt->streamDone += dataIn;
|
||||
|
||||
// update datacrc
|
||||
BLO_decrypt->datacrc = crc32(
|
||||
BLO_decrypt->datacrc, (const Bytef *) data, dataIn);
|
||||
|
||||
// TODO FIXME we might need to keylength-align the data !
|
||||
RC4(&(BLO_decrypt->rc4_key), dataIn, data, deCryptBuf);
|
||||
|
||||
// give data to streamGlueRead, it will find out what to do next
|
||||
err = readStreamGlue(
|
||||
BLO_decrypt->endControl,
|
||||
&(BLO_decrypt->streamGlue),
|
||||
(unsigned char *) deCryptBuf,
|
||||
dataIn);
|
||||
|
||||
free(deCryptBuf);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* openssl decrypt final call and cleanup
|
||||
* @param BLO_decrypt Pointer to decrypt control structure
|
||||
* @retval streamGlueRead return value
|
||||
*/
|
||||
int
|
||||
BLO_decrypt_end(
|
||||
BLO_decryptStructHandle BLO_decryptHandle)
|
||||
{
|
||||
int err = 0;
|
||||
struct decryptStructType *BLO_decrypt =
|
||||
(struct decryptStructType *) BLO_decryptHandle;
|
||||
|
||||
if (!BLO_decrypt) {
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_NULL);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (BLO_decrypt->streamDone == BLO_decrypt->streamHeader->length +
|
||||
EN_DE_CRYPTHEADERSTRUCTSIZE) {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream, "Crypted data length is correct\n");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream, "Crypted data length is NOT correct\n");
|
||||
#endif
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_DATALEN);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (BLO_decrypt->datacrc == BLO_decrypt->streamHeader->datacrc) {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream, "Crypted data CRC is correct\n");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
fprintf(GEN_errorstream, "Crypted data CRC is NOT correct\n");
|
||||
#endif
|
||||
err = BRS_SETFUNCTION(BRS_DECRYPT) |
|
||||
BRS_SETGENERR(BRS_CRCDATA);
|
||||
if (BLO_decrypt->streamGlue) free(BLO_decrypt->streamGlue);
|
||||
if (BLO_decrypt->streamHeader) free(BLO_decrypt->streamHeader);
|
||||
if (BLO_decrypt->deCryptKey) free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
return err;
|
||||
}
|
||||
|
||||
free(BLO_decrypt->streamGlue);
|
||||
free(BLO_decrypt->streamHeader);
|
||||
free(BLO_decrypt->deCryptKey);
|
||||
free(BLO_decrypt);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
Reference in New Issue
Block a user