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
Kent Mein 3c7c20676e This is a fun one ;)
Removes ssl from blender.
makes the following directorys not needed anymore:
blender/intern/keymaker
blender/source/blender/src/pub
blender/source/blender/encrypt
blender/source/blender/decrypt
blender/source/blender/sign
blender/source/blender/verify

It works with The Nan Makefiles and autoconf, could whoever is working
on the other build systems update them so we can nuke those directorys?
They won't do anything but I figured I'd leave them in for a week or so
to make things easyer on people.

Kent
2003-05-30 15:06:54 +00:00

399 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 "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;
unsigned char *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;
}