This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/decrypt/intern/BLO_decrypt.c

400 lines
12 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 *****
* openssl decryption wrapper library
*/
#include <stdio.h>
#include <string.h> /* memcpy, strcpy */
#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"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
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;
}