First new particle code:
[blender-staging.git] / source / blender / verify / intern / BLO_verify.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * openssl verify wrapper library
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "openssl/rsa.h"
36 #include "openssl/ripemd.h"
37 #include "openssl/objects.h"
38 #include "zlib.h"
39
40 #include "GEN_messaging.h"
41
42 #include "BLO_readStreamGlue.h"
43 #include "BLO_verify.h"
44 #include "BLO_sign_verify_Header.h"     /* used by verify and encrypt */
45
46 #include "BLO_signer_info.h" /* external signer info struct */
47
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51
52 static struct BLO_SignerInfo g_SignerInfo = {"", "", ""};
53
54 struct verifyStructType {
55         struct readStreamGlueStruct *streamGlue;
56         unsigned int streamDone;
57         unsigned char headerbuffer[SIGNVERIFYHEADERSTRUCTSIZE];
58         uint32_t datacrc;
59         struct BLO_sign_verify_HeaderStruct *streamHeader;
60         RIPEMD160_CTX ripemd160_ctx;
61         struct BLO_SignerHeaderStruct *signerHeader;
62         unsigned char signerHeaderBuffer[SIGNERHEADERSTRUCTSIZE];
63         void *endControl;
64 };
65
66         BLO_verifyStructHandle
67 BLO_verify_begin(
68         void *endControl)
69 {
70         struct verifyStructType *control;
71         control = malloc(sizeof(struct verifyStructType));
72         if (!control) return NULL;
73
74         control->streamGlue = NULL;
75         control->streamDone = 0;
76         memset(control->headerbuffer, 0, SIGNVERIFYHEADERSTRUCTSIZE);
77         control->datacrc = 0;
78
79         control->streamHeader = malloc(SIGNVERIFYHEADERSTRUCTSIZE);
80         if (!control->streamHeader) {
81                 free(control);
82                 return NULL;
83         }
84         control->streamHeader->magic = 0;
85         control->streamHeader->length = 0;
86         strcpy(control->streamHeader->pubKey, "");
87         control->streamHeader->pubKeyLen = 0;
88         strcpy(control->streamHeader->signature, "");
89         control->streamHeader->signatureLen = 0;
90         control->streamHeader->datacrc = 0;
91         control->streamHeader->headercrc = 0;
92
93         RIPEMD160_Init(&(control->ripemd160_ctx));
94
95         control->signerHeader = malloc(SIGNERHEADERSTRUCTSIZE);
96         if (!control->signerHeader) {
97                 free(control->streamHeader);
98                 free(control);
99                 return NULL;
100         }
101         memset(control->signerHeader->name,       0, MAXSIGNERLEN);
102         memset(control->signerHeader->email,      0, MAXSIGNERLEN);
103         memset(control->signerHeader->homeUrl,    0, MAXSIGNERLEN);
104         memset(control->signerHeader->text,       0, MAXSIGNERLEN);
105         memset(control->signerHeader->pubKeyUrl1, 0, MAXSIGNERLEN);
106         memset(control->signerHeader->pubKeyUrl2, 0, MAXSIGNERLEN);
107
108         control->endControl = endControl;
109         return((BLO_verifyStructHandle) control);
110 }
111
112         int
113 BLO_verify_process(
114         BLO_verifyStructHandle BLO_verifyHandle,
115         unsigned char *data,
116         unsigned int dataIn)
117 {
118         int err = 0;
119         struct verifyStructType *BLO_verify =
120                 (struct verifyStructType *) BLO_verifyHandle;
121
122         if (!BLO_verify) {
123                 err = BRS_SETFUNCTION(BRS_VERIFY) |
124                           BRS_SETGENERR(BRS_NULL);
125                 return err;
126         }
127
128         /* First check if we have our header filled in yet */
129         if (BLO_verify->streamHeader->length == 0) {
130                 unsigned int processed;
131                 if (dataIn == 0) return err;    /* really need data to do anything */
132                 processed = ((dataIn + BLO_verify->streamDone) <=
133                                          SIGNVERIFYHEADERSTRUCTSIZE)
134                                          ? dataIn : SIGNVERIFYHEADERSTRUCTSIZE;
135                 memcpy(BLO_verify->headerbuffer + BLO_verify->streamDone,
136                            data, processed);
137                 BLO_verify->streamDone += processed;
138                 dataIn -= processed;
139                 data += processed;
140                 if (BLO_verify->streamDone == SIGNVERIFYHEADERSTRUCTSIZE) {
141                         /* we have the whole header, absorb it */
142                         struct BLO_sign_verify_HeaderStruct *header;
143                         uint32_t crc;
144
145                         header = (struct BLO_sign_verify_HeaderStruct *)
146                                 BLO_verify->headerbuffer;
147                         crc = crc32(0L, (const Bytef *) header,
148                                                 SIGNVERIFYHEADERSTRUCTSIZE - 4);
149
150                         if (header->magic == 'A') {
151 #ifndef NDEBUG
152                                 fprintf(GEN_errorstream,
153                                                 "BLO_sign_verify_HeaderStruct Magic confirmed\n");
154 #endif
155                         } else {
156 #ifndef NDEBUG
157                                 fprintf(GEN_errorstream,
158                                                 "ERROR BLO_sign_verify_HeaderStruct Magic NOT confirmed\n");
159 #endif
160                                 err = BRS_SETFUNCTION(BRS_VERIFY) |
161                                           BRS_SETGENERR(BRS_MAGIC);
162                                 if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
163                                 if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
164                                 if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
165                                 free(BLO_verify);
166                                 return err;
167                         }
168
169                         if (crc == ntohl(header->headercrc)) {
170 #ifndef NDEBUG                          
171                                 fprintf(GEN_errorstream,"BLO_sign_verify_Header CRC correct\n");
172 #endif
173                         } else {
174 #ifndef NDEBUG
175                                 fprintf(GEN_errorstream,"ERROR BLO_sign_verify_Header CRC NOT correct\n");
176 #endif
177                                 err = BRS_SETFUNCTION(BRS_VERIFY) |
178                                           BRS_SETGENERR(BRS_CRCHEADER);
179                                 if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
180                                 if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
181                                 if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
182                                 free(BLO_verify);
183                                 return err;
184                         }
185                         BLO_verify->streamHeader->length = ntohl(header->length);
186                         BLO_verify->streamHeader->pubKeyLen = ntohl(header->pubKeyLen);
187                         memcpy(BLO_verify->streamHeader->pubKey, header->pubKey,
188                                    BLO_verify->streamHeader->pubKeyLen);
189                         BLO_verify->streamHeader->signatureLen =
190                                 ntohl(header->signatureLen);
191                         memcpy(BLO_verify->streamHeader->signature, header->signature,
192                                    BLO_verify->streamHeader->signatureLen);
193                         BLO_verify->streamHeader->datacrc = ntohl(header->datacrc);
194
195 #ifndef NDEBUG
196                         fprintf(GEN_errorstream,
197                                         "BLO_verify_process gets %u bytes\n",
198                                         (unsigned int) BLO_verify->streamHeader->length);
199 #endif
200
201                 }
202         }
203
204         /* Is there really (still) new data available ? */
205         if (dataIn > 0) {
206                 /* BLO_SignerHeaderStruct */
207                 if (BLO_verify->signerHeader->name[0] == 0) {
208                         /* we don't have our signerHeader complete yet */
209                         unsigned int processed;
210                         processed = ((dataIn + BLO_verify->streamDone -
211                                 SIGNVERIFYHEADERSTRUCTSIZE) <= SIGNERHEADERSTRUCTSIZE)
212                                 ? dataIn : SIGNERHEADERSTRUCTSIZE;
213                         memcpy(BLO_verify->signerHeaderBuffer +
214                                    BLO_verify->streamDone - SIGNVERIFYHEADERSTRUCTSIZE,
215                                    data, processed);
216                         BLO_verify->streamDone += processed;
217                         dataIn -= processed;
218                         data += processed;
219                         if (BLO_verify->streamDone == SIGNVERIFYHEADERSTRUCTSIZE +
220                                 SIGNERHEADERSTRUCTSIZE) {
221                                 /* we have the whole header, absorb it */
222                                 struct BLO_SignerHeaderStruct *signerHeader;
223                                 signerHeader = (struct BLO_SignerHeaderStruct *)
224                                         BLO_verify->signerHeaderBuffer;
225                                 strncpy(BLO_verify->signerHeader->name,
226                                                 signerHeader->name, MAXSIGNERLEN-1);
227                                 strncpy(BLO_verify->signerHeader->email,
228                                                 signerHeader->email, MAXSIGNERLEN-1);
229                                 strncpy(BLO_verify->signerHeader->homeUrl,
230                                            signerHeader->homeUrl, MAXSIGNERLEN-1);
231                                 strncpy(BLO_verify->signerHeader->text,
232                                                 signerHeader->text, MAXSIGNERLEN-1);
233                                 strncpy(BLO_verify->signerHeader->pubKeyUrl1,
234                                            signerHeader->pubKeyUrl1, MAXSIGNERLEN-1);
235                                 strncpy(BLO_verify->signerHeader->pubKeyUrl2,
236                                            signerHeader->pubKeyUrl2, MAXSIGNERLEN-1);
237
238 #ifndef NDEBUG
239                                 fprintf(GEN_errorstream,
240                                         "name %s\nemail %s\nhomeUrl %s\ntext %s\n",
241                                         BLO_verify->signerHeader->name,
242                                         BLO_verify->signerHeader->email,
243                                         BLO_verify->signerHeader->homeUrl,
244                                         BLO_verify->signerHeader->text);
245                                 fprintf(GEN_errorstream,
246                                         "pubKeyUrl1 %s\npubKeyUrl2 %s\n",
247                                         BLO_verify->signerHeader->pubKeyUrl1,
248                                         BLO_verify->signerHeader->pubKeyUrl2);
249 #endif
250                                 /* also update the signature and crc checksum */
251                                 RIPEMD160_Update(&(BLO_verify->ripemd160_ctx),
252                                                                  BLO_verify->signerHeaderBuffer,
253                                                                  SIGNERHEADERSTRUCTSIZE);
254
255                                 /* update datacrc */
256                                 BLO_verify->datacrc = crc32(
257                                         BLO_verify->datacrc, (const Bytef *)
258                                         BLO_verify->signerHeaderBuffer,
259                                         SIGNERHEADERSTRUCTSIZE);
260                         }
261                 }
262         }
263
264         /* Is there really (still) new data available ? */
265         if (dataIn > 0) {
266                 RIPEMD160_Update(&(BLO_verify->ripemd160_ctx), data, dataIn);
267
268                 /* update datacrc */
269                 BLO_verify->datacrc = crc32(
270                         BLO_verify->datacrc, (const Bytef *) data, dataIn);
271
272                 BLO_verify->streamDone += dataIn;
273
274                 /* give data to streamGlueRead, it will find out what to do next */
275                 err = readStreamGlue(
276                         BLO_verify->endControl,
277                         &(BLO_verify->streamGlue),
278                         (unsigned char *) data,
279                         dataIn);
280         }
281         return err;
282 }
283
284 /**
285  * openssl verify final call and cleanup
286  * @param BLO_verify Pointer to verify control structure
287  * @retval streamGlueRead return value
288  */
289         int
290 BLO_verify_end(
291         BLO_verifyStructHandle BLO_verifyHandle)
292 {
293         int err = 0;
294         unsigned char *digest;
295         static unsigned char rsa_e[] = "\x01\x00\x01";
296         RSA *rsa = NULL;
297         int verifySuccess;
298         struct verifyStructType *BLO_verify =
299                 (struct verifyStructType *) BLO_verifyHandle;
300
301         if (!BLO_verify) {
302                 err = BRS_SETFUNCTION(BRS_VERIFY) |
303                           BRS_SETGENERR(BRS_NULL);
304                 return err;
305         }
306
307         if (BLO_verify->streamDone == BLO_verify->streamHeader->length +
308                 SIGNVERIFYHEADERSTRUCTSIZE) {
309 #ifndef NDEBUG
310                 fprintf(GEN_errorstream, "Signed data length is correct\n");
311 #endif
312         } else {
313 #ifndef NDEBUG
314                 fprintf(GEN_errorstream, "Signed data length is NOT correct\n");
315 #endif
316                 err = BRS_SETFUNCTION(BRS_VERIFY) |
317                           BRS_SETGENERR(BRS_DATALEN);
318                 if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
319                 if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
320                 if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
321                 free(BLO_verify);
322                 return err;
323         }
324
325         if (BLO_verify->datacrc == BLO_verify->streamHeader->datacrc) {
326 #ifndef NDEBUG
327                 fprintf(GEN_errorstream, "Signed data CRC is correct\n");
328 #endif
329         } else {
330 #ifndef NDEBUG
331                 fprintf(GEN_errorstream, "Signed data CRC is NOT correct\n");
332 #endif
333                 err = BRS_SETFUNCTION(BRS_VERIFY) |
334                           BRS_SETGENERR(BRS_CRCDATA);
335                 if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
336                 if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
337                 if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
338                 free(BLO_verify);
339                 return err;
340         }
341
342         digest = malloc(RIPEMD160_DIGEST_LENGTH);
343         if (!digest) {
344                 err = BRS_SETFUNCTION(BRS_VERIFY) |
345                           BRS_SETGENERR(BRS_MALLOC);
346                 if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
347                 if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
348                 if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
349                 free(BLO_verify);
350                 return err;
351         }
352
353         RIPEMD160_Final(digest, &(BLO_verify->ripemd160_ctx));
354
355         rsa = RSA_new();
356         if (rsa == NULL) {
357 #ifndef NDEBUG
358                 fprintf(GEN_errorstream, "Error in RSA_new\n");
359 #endif
360                 err = BRS_SETFUNCTION(BRS_VERIFY) |
361                           BRS_SETSPECERR(BRS_RSANEWERROR);
362                 free(digest);
363                 if (BLO_verify->streamGlue) free(BLO_verify->streamGlue);
364                 if (BLO_verify->streamHeader) free(BLO_verify->streamHeader);
365                 if (BLO_verify->signerHeader) free(BLO_verify->signerHeader);
366                 free(BLO_verify);
367                 return err;
368         }
369         /* static exponent */
370         rsa->e = BN_bin2bn(rsa_e, sizeof(rsa_e)-1, rsa->e);
371
372         /* public part into rsa->n */
373         rsa->n = BN_bin2bn(BLO_verify->streamHeader->pubKey,
374                                            BLO_verify->streamHeader->pubKeyLen,
375                                            rsa->n);
376         /*DEBUG RSA_print_fp(stdout, rsa, 0); */
377
378         /* verify the signature */
379         verifySuccess = RSA_verify(NID_ripemd160, digest, RIPEMD160_DIGEST_LENGTH,
380                                BLO_verify->streamHeader->signature,
381                                    BLO_verify->streamHeader->signatureLen, rsa);
382         if (verifySuccess == 1) {
383 #ifndef NDEBUG
384                 fprintf(GEN_errorstream,
385                                 "Signature verified\n");
386 #endif
387         } else {
388 #ifndef NDEBUG
389                 fprintf(GEN_errorstream,
390                                 "Signature INCORRECT\n");
391 #endif
392                 err = BRS_SETFUNCTION(BRS_VERIFY) |
393                           BRS_SETSPECERR(BRS_SIGFAILED);
394         }
395
396 /* copy signer information to external struct  */
397         
398         strncpy(g_SignerInfo.name, BLO_verify->signerHeader->name, MAXSIGNERLEN-1);
399         strncpy(g_SignerInfo.email, BLO_verify->signerHeader->email, MAXSIGNERLEN-1);
400         strncpy(g_SignerInfo.homeUrl, BLO_verify->signerHeader->homeUrl, MAXSIGNERLEN-1);
401
402         free(digest);
403         free(BLO_verify->streamGlue);
404         free(BLO_verify->streamHeader);
405         free(BLO_verify->signerHeader);
406         free(BLO_verify);
407         RSA_free(rsa);
408
409         return err;
410 }
411
412 struct BLO_SignerInfo *BLO_getSignerInfo(){
413         return &g_SignerInfo;
414 }
415
416 int BLO_isValidSignerInfo(struct BLO_SignerInfo *info){
417         return info->name[0] != 0;
418 }
419
420 void BLO_clrSignerInfo(struct BLO_SignerInfo *info)
421 {
422         info->name[0] = 0;
423 }
424