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