diff options
Diffstat (limited to 'source/blender/verify/intern/BLO_verify.c')
-rw-r--r-- | source/blender/verify/intern/BLO_verify.c | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/source/blender/verify/intern/BLO_verify.c b/source/blender/verify/intern/BLO_verify.c new file mode 100644 index 00000000000..f9c71be1432 --- /dev/null +++ b/source/blender/verify/intern/BLO_verify.c @@ -0,0 +1,423 @@ +/** + * $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 verify wrapper library + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "openssl/rsa.h" +#include "openssl/ripemd.h" +#include "openssl/objects.h" +#include "zlib.h" + +#include "GEN_messaging.h" + +#include "BLO_readStreamGlue.h" +#include "BLO_verify.h" +#include "BLO_sign_verify_Header.h" /* used by verify and encrypt */ + +#include "BLO_signer_info.h" // external signer info struct + +static struct BLO_SignerInfo g_SignerInfo = {"", "", ""}; + +struct verifyStructType { + struct readStreamGlueStruct *streamGlue; + unsigned int streamDone; + unsigned char headerbuffer[SIGNVERIFYHEADERSTRUCTSIZE]; + uint32_t datacrc; + struct BLO_sign_verify_HeaderStruct *streamHeader; + RIPEMD160_CTX ripemd160_ctx; + struct BLO_SignerHeaderStruct *signerHeader; + unsigned char signerHeaderBuffer[SIGNERHEADERSTRUCTSIZE]; + void *endControl; +}; + + BLO_verifyStructHandle +BLO_verify_begin( + void *endControl) +{ + struct verifyStructType *control; + control = malloc(sizeof(struct verifyStructType)); + if (!control) return NULL; + + control->streamGlue = NULL; + control->streamDone = 0; + memset(control->headerbuffer, 0, SIGNVERIFYHEADERSTRUCTSIZE); + control->datacrc = 0; + + control->streamHeader = malloc(SIGNVERIFYHEADERSTRUCTSIZE); + 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->signature, ""); + control->streamHeader->signatureLen = 0; + control->streamHeader->datacrc = 0; + control->streamHeader->headercrc = 0; + + RIPEMD160_Init(&(control->ripemd160_ctx)); + + control->signerHeader = malloc(SIGNERHEADERSTRUCTSIZE); + if (!control->signerHeader) { + free(control->streamHeader); + free(control); + return NULL; + } + memset(control->signerHeader->name, 0, MAXSIGNERLEN); + memset(control->signerHeader->email, 0, MAXSIGNERLEN); + memset(control->signerHeader->homeUrl, 0, MAXSIGNERLEN); + memset(control->signerHeader->text, 0, MAXSIGNERLEN); + memset(control->signerHeader->pubKeyUrl1, 0, MAXSIGNERLEN); + memset(control->signerHeader->pubKeyUrl2, 0, MAXSIGNERLEN); + + control->endControl = endControl; + return((BLO_verifyStructHandle) control); +} + + int +BLO_verify_process( + BLO_verifyStructHandle BLO_verifyHandle, + unsigned char *data, + unsigned int dataIn) +{ + int err = 0; + struct verifyStructType *BLO_verify = + (struct verifyStructType *) BLO_verifyHandle; + + if (!BLO_verify) { + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETGENERR(BRS_NULL); + return err; + } + + /* First check if we have our header filled in yet */ + if (BLO_verify->streamHeader->length == 0) { + unsigned int processed; + if (dataIn == 0) return err; /* really need data to do anything */ + processed = ((dataIn + BLO_verify->streamDone) <= + SIGNVERIFYHEADERSTRUCTSIZE) + ? dataIn : SIGNVERIFYHEADERSTRUCTSIZE; + memcpy(BLO_verify->headerbuffer + BLO_verify->streamDone, + data, processed); + BLO_verify->streamDone += processed; + dataIn -= processed; + data += processed; + if (BLO_verify->streamDone == SIGNVERIFYHEADERSTRUCTSIZE) { + /* we have the whole header, absorb it */ + struct BLO_sign_verify_HeaderStruct *header; + uint32_t crc; + + header = (struct BLO_sign_verify_HeaderStruct *) + BLO_verify->headerbuffer; + crc = crc32(0L, (const Bytef *) header, + SIGNVERIFYHEADERSTRUCTSIZE - 4); + + if (header->magic == 'A') { +#ifndef NDEBUG + fprintf(GEN_errorstream, + "BLO_sign_verify_HeaderStruct Magic confirmed\n"); +#endif + } else { +#ifndef NDEBUG + fprintf(GEN_errorstream, + "ERROR BLO_sign_verify_HeaderStruct Magic NOT confirmed\n"); +#endif + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETGENERR(BRS_MAGIC); + if (BLO_verify->streamGlue) free(BLO_verify->streamGlue); + if (BLO_verify->streamHeader) free(BLO_verify->streamHeader); + if (BLO_verify->signerHeader) free(BLO_verify->signerHeader); + free(BLO_verify); + return err; + } + + if (crc == ntohl(header->headercrc)) { +#ifndef NDEBUG + fprintf(GEN_errorstream,"BLO_sign_verify_Header CRC correct\n"); +#endif + } else { +#ifndef NDEBUG + fprintf(GEN_errorstream,"ERROR BLO_sign_verify_Header CRC NOT correct\n"); +#endif + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETGENERR(BRS_CRCHEADER); + if (BLO_verify->streamGlue) free(BLO_verify->streamGlue); + if (BLO_verify->streamHeader) free(BLO_verify->streamHeader); + if (BLO_verify->signerHeader) free(BLO_verify->signerHeader); + free(BLO_verify); + return err; + } + BLO_verify->streamHeader->length = ntohl(header->length); + BLO_verify->streamHeader->pubKeyLen = ntohl(header->pubKeyLen); + memcpy(BLO_verify->streamHeader->pubKey, header->pubKey, + BLO_verify->streamHeader->pubKeyLen); + BLO_verify->streamHeader->signatureLen = + ntohl(header->signatureLen); + memcpy(BLO_verify->streamHeader->signature, header->signature, + BLO_verify->streamHeader->signatureLen); + BLO_verify->streamHeader->datacrc = ntohl(header->datacrc); + +#ifndef NDEBUG + fprintf(GEN_errorstream, + "BLO_verify_process gets %u bytes\n", + (unsigned int) BLO_verify->streamHeader->length); +#endif + + } + } + + /* Is there really (still) new data available ? */ + if (dataIn > 0) { + // BLO_SignerHeaderStruct + if (BLO_verify->signerHeader->name[0] == 0) { + // we don't have our signerHeader complete yet + unsigned int processed; + processed = ((dataIn + BLO_verify->streamDone - + SIGNVERIFYHEADERSTRUCTSIZE) <= SIGNERHEADERSTRUCTSIZE) + ? dataIn : SIGNERHEADERSTRUCTSIZE; + memcpy(BLO_verify->signerHeaderBuffer + + BLO_verify->streamDone - SIGNVERIFYHEADERSTRUCTSIZE, + data, processed); + BLO_verify->streamDone += processed; + dataIn -= processed; + data += processed; + if (BLO_verify->streamDone == SIGNVERIFYHEADERSTRUCTSIZE + + SIGNERHEADERSTRUCTSIZE) { + // we have the whole header, absorb it + struct BLO_SignerHeaderStruct *signerHeader; + signerHeader = (struct BLO_SignerHeaderStruct *) + BLO_verify->signerHeaderBuffer; + strncpy(BLO_verify->signerHeader->name, + signerHeader->name, MAXSIGNERLEN-1); + strncpy(BLO_verify->signerHeader->email, + signerHeader->email, MAXSIGNERLEN-1); + strncpy(BLO_verify->signerHeader->homeUrl, + signerHeader->homeUrl, MAXSIGNERLEN-1); + strncpy(BLO_verify->signerHeader->text, + signerHeader->text, MAXSIGNERLEN-1); + strncpy(BLO_verify->signerHeader->pubKeyUrl1, + signerHeader->pubKeyUrl1, MAXSIGNERLEN-1); + strncpy(BLO_verify->signerHeader->pubKeyUrl2, + signerHeader->pubKeyUrl2, MAXSIGNERLEN-1); + +#ifndef NDEBUG + fprintf(GEN_errorstream, + "name %s\nemail %s\nhomeUrl %s\ntext %s\n", + BLO_verify->signerHeader->name, + BLO_verify->signerHeader->email, + BLO_verify->signerHeader->homeUrl, + BLO_verify->signerHeader->text); + fprintf(GEN_errorstream, + "pubKeyUrl1 %s\npubKeyUrl2 %s\n", + BLO_verify->signerHeader->pubKeyUrl1, + BLO_verify->signerHeader->pubKeyUrl2); +#endif + // also update the signature and crc checksum + RIPEMD160_Update(&(BLO_verify->ripemd160_ctx), + BLO_verify->signerHeaderBuffer, + SIGNERHEADERSTRUCTSIZE); + + // update datacrc + BLO_verify->datacrc = crc32( + BLO_verify->datacrc, (const Bytef *) + BLO_verify->signerHeaderBuffer, + SIGNERHEADERSTRUCTSIZE); + } + } + } + + /* Is there really (still) new data available ? */ + if (dataIn > 0) { + RIPEMD160_Update(&(BLO_verify->ripemd160_ctx), data, dataIn); + + // update datacrc + BLO_verify->datacrc = crc32( + BLO_verify->datacrc, (const Bytef *) data, dataIn); + + BLO_verify->streamDone += dataIn; + + // give data to streamGlueRead, it will find out what to do next + err = readStreamGlue( + BLO_verify->endControl, + &(BLO_verify->streamGlue), + (unsigned char *) data, + dataIn); + } + return err; +} + +/** + * openssl verify final call and cleanup + * @param BLO_verify Pointer to verify control structure + * @retval streamGlueRead return value + */ + int +BLO_verify_end( + BLO_verifyStructHandle BLO_verifyHandle) +{ + int err = 0; + unsigned char *digest; + static unsigned char rsa_e[] = "\x01\x00\x01"; + RSA *rsa = NULL; + int verifySuccess; + struct verifyStructType *BLO_verify = + (struct verifyStructType *) BLO_verifyHandle; + + if (!BLO_verify) { + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETGENERR(BRS_NULL); + return err; + } + + if (BLO_verify->streamDone == BLO_verify->streamHeader->length + + SIGNVERIFYHEADERSTRUCTSIZE) { +#ifndef NDEBUG + fprintf(GEN_errorstream, "Signed data length is correct\n"); +#endif + } else { +#ifndef NDEBUG + fprintf(GEN_errorstream, "Signed data length is NOT correct\n"); +#endif + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETGENERR(BRS_DATALEN); + if (BLO_verify->streamGlue) free(BLO_verify->streamGlue); + if (BLO_verify->streamHeader) free(BLO_verify->streamHeader); + if (BLO_verify->signerHeader) free(BLO_verify->signerHeader); + free(BLO_verify); + return err; + } + + if (BLO_verify->datacrc == BLO_verify->streamHeader->datacrc) { +#ifndef NDEBUG + fprintf(GEN_errorstream, "Signed data CRC is correct\n"); +#endif + } else { +#ifndef NDEBUG + fprintf(GEN_errorstream, "Signed data CRC is NOT correct\n"); +#endif + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETGENERR(BRS_CRCDATA); + if (BLO_verify->streamGlue) free(BLO_verify->streamGlue); + if (BLO_verify->streamHeader) free(BLO_verify->streamHeader); + if (BLO_verify->signerHeader) free(BLO_verify->signerHeader); + free(BLO_verify); + return err; + } + + digest = malloc(RIPEMD160_DIGEST_LENGTH); + if (!digest) { + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETGENERR(BRS_MALLOC); + if (BLO_verify->streamGlue) free(BLO_verify->streamGlue); + if (BLO_verify->streamHeader) free(BLO_verify->streamHeader); + if (BLO_verify->signerHeader) free(BLO_verify->signerHeader); + free(BLO_verify); + return err; + } + + RIPEMD160_Final(digest, &(BLO_verify->ripemd160_ctx)); + + rsa = RSA_new(); + if (rsa == NULL) { +#ifndef NDEBUG + fprintf(GEN_errorstream, "Error in RSA_new\n"); +#endif + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETSPECERR(BRS_RSANEWERROR); + free(digest); + if (BLO_verify->streamGlue) free(BLO_verify->streamGlue); + if (BLO_verify->streamHeader) free(BLO_verify->streamHeader); + if (BLO_verify->signerHeader) free(BLO_verify->signerHeader); + free(BLO_verify); + 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(BLO_verify->streamHeader->pubKey, + BLO_verify->streamHeader->pubKeyLen, + rsa->n); + //DEBUG RSA_print_fp(stdout, rsa, 0); + + // verify the signature + verifySuccess = RSA_verify(NID_ripemd160, digest, RIPEMD160_DIGEST_LENGTH, + BLO_verify->streamHeader->signature, + BLO_verify->streamHeader->signatureLen, rsa); + if (verifySuccess == 1) { +#ifndef NDEBUG + fprintf(GEN_errorstream, + "Signature verified\n"); +#endif + } else { +#ifndef NDEBUG + fprintf(GEN_errorstream, + "Signature INCORRECT\n"); +#endif + err = BRS_SETFUNCTION(BRS_VERIFY) | + BRS_SETSPECERR(BRS_SIGFAILED); + } + +// copy signer information to external struct + + strncpy(g_SignerInfo.name, BLO_verify->signerHeader->name, MAXSIGNERLEN-1); + strncpy(g_SignerInfo.email, BLO_verify->signerHeader->email, MAXSIGNERLEN-1); + strncpy(g_SignerInfo.homeUrl, BLO_verify->signerHeader->homeUrl, MAXSIGNERLEN-1); +// + free(digest); + free(BLO_verify->streamGlue); + free(BLO_verify->streamHeader); + free(BLO_verify->signerHeader); + free(BLO_verify); + RSA_free(rsa); + + return err; +} + +struct BLO_SignerInfo *BLO_getSignerInfo(){ + return &g_SignerInfo; +} + +int BLO_isValidSignerInfo(struct BLO_SignerInfo *info){ + return info->name[0] != 0; +} + +void BLO_clrSignerInfo(struct BLO_SignerInfo *info) +{ + info->name[0] = 0; +} + |