source: trunk/library/sha1.c @ 1159

Revision 1159, 16.0 KB checked in by paul, 2 months ago (diff)
  • Changed the behaviour of x509parse_parse_crt for permissive parsing. Now returns the number of 'failed certificates' instead of having a switch to enable it.
  • As a consequence all error code that were positive were changed. A lot of MALLOC_FAILED and FILE_IO_ERROR error codes added for different modules.
  • Programs and tests were adapted accordingly
Line 
1/*
2 *  FIPS-180-1 compliant SHA-1 implementation
3 *
4 *  Copyright (C) 2006-2010, Brainspark B.V.
5 *
6 *  This file is part of PolarSSL (http://www.polarssl.org)
7 *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 *  All rights reserved.
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation; either version 2 of the License, or
14 *  (at your option) any later version.
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 *  GNU General Public License for more details.
20 *
21 *  You should have received a copy of the GNU General Public License along
22 *  with this program; if not, write to the Free Software Foundation, Inc.,
23 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25/*
26 *  The SHA-1 standard was published by NIST in 1993.
27 *
28 *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
29 */
30
31#include "polarssl/config.h"
32
33#if defined(POLARSSL_SHA1_C)
34
35#include "polarssl/sha1.h"
36
37#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
38#include <stdio.h>
39#endif
40
41/*
42 * 32-bit integer manipulation macros (big endian)
43 */
44#ifndef GET_ULONG_BE
45#define GET_ULONG_BE(n,b,i)                             \
46{                                                       \
47    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
48        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
49        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
50        | ( (unsigned long) (b)[(i) + 3]       );       \
51}
52#endif
53
54#ifndef PUT_ULONG_BE
55#define PUT_ULONG_BE(n,b,i)                             \
56{                                                       \
57    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
58    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
59    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
60    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
61}
62#endif
63
64/*
65 * SHA-1 context setup
66 */
67void sha1_starts( sha1_context *ctx )
68{
69    ctx->total[0] = 0;
70    ctx->total[1] = 0;
71
72    ctx->state[0] = 0x67452301;
73    ctx->state[1] = 0xEFCDAB89;
74    ctx->state[2] = 0x98BADCFE;
75    ctx->state[3] = 0x10325476;
76    ctx->state[4] = 0xC3D2E1F0;
77}
78
79static void sha1_process( sha1_context *ctx, const unsigned char data[64] )
80{
81    unsigned long temp, W[16], A, B, C, D, E;
82
83    GET_ULONG_BE( W[ 0], data,  0 );
84    GET_ULONG_BE( W[ 1], data,  4 );
85    GET_ULONG_BE( W[ 2], data,  8 );
86    GET_ULONG_BE( W[ 3], data, 12 );
87    GET_ULONG_BE( W[ 4], data, 16 );
88    GET_ULONG_BE( W[ 5], data, 20 );
89    GET_ULONG_BE( W[ 6], data, 24 );
90    GET_ULONG_BE( W[ 7], data, 28 );
91    GET_ULONG_BE( W[ 8], data, 32 );
92    GET_ULONG_BE( W[ 9], data, 36 );
93    GET_ULONG_BE( W[10], data, 40 );
94    GET_ULONG_BE( W[11], data, 44 );
95    GET_ULONG_BE( W[12], data, 48 );
96    GET_ULONG_BE( W[13], data, 52 );
97    GET_ULONG_BE( W[14], data, 56 );
98    GET_ULONG_BE( W[15], data, 60 );
99
100#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
101
102#define R(t)                                            \
103(                                                       \
104    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
105           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \
106    ( W[t & 0x0F] = S(temp,1) )                         \
107)
108
109#define P(a,b,c,d,e,x)                                  \
110{                                                       \
111    e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \
112}
113
114    A = ctx->state[0];
115    B = ctx->state[1];
116    C = ctx->state[2];
117    D = ctx->state[3];
118    E = ctx->state[4];
119
120#define F(x,y,z) (z ^ (x & (y ^ z)))
121#define K 0x5A827999
122
123    P( A, B, C, D, E, W[0]  );
124    P( E, A, B, C, D, W[1]  );
125    P( D, E, A, B, C, W[2]  );
126    P( C, D, E, A, B, W[3]  );
127    P( B, C, D, E, A, W[4]  );
128    P( A, B, C, D, E, W[5]  );
129    P( E, A, B, C, D, W[6]  );
130    P( D, E, A, B, C, W[7]  );
131    P( C, D, E, A, B, W[8]  );
132    P( B, C, D, E, A, W[9]  );
133    P( A, B, C, D, E, W[10] );
134    P( E, A, B, C, D, W[11] );
135    P( D, E, A, B, C, W[12] );
136    P( C, D, E, A, B, W[13] );
137    P( B, C, D, E, A, W[14] );
138    P( A, B, C, D, E, W[15] );
139    P( E, A, B, C, D, R(16) );
140    P( D, E, A, B, C, R(17) );
141    P( C, D, E, A, B, R(18) );
142    P( B, C, D, E, A, R(19) );
143
144#undef K
145#undef F
146
147#define F(x,y,z) (x ^ y ^ z)
148#define K 0x6ED9EBA1
149
150    P( A, B, C, D, E, R(20) );
151    P( E, A, B, C, D, R(21) );
152    P( D, E, A, B, C, R(22) );
153    P( C, D, E, A, B, R(23) );
154    P( B, C, D, E, A, R(24) );
155    P( A, B, C, D, E, R(25) );
156    P( E, A, B, C, D, R(26) );
157    P( D, E, A, B, C, R(27) );
158    P( C, D, E, A, B, R(28) );
159    P( B, C, D, E, A, R(29) );
160    P( A, B, C, D, E, R(30) );
161    P( E, A, B, C, D, R(31) );
162    P( D, E, A, B, C, R(32) );
163    P( C, D, E, A, B, R(33) );
164    P( B, C, D, E, A, R(34) );
165    P( A, B, C, D, E, R(35) );
166    P( E, A, B, C, D, R(36) );
167    P( D, E, A, B, C, R(37) );
168    P( C, D, E, A, B, R(38) );
169    P( B, C, D, E, A, R(39) );
170
171#undef K
172#undef F
173
174#define F(x,y,z) ((x & y) | (z & (x | y)))
175#define K 0x8F1BBCDC
176
177    P( A, B, C, D, E, R(40) );
178    P( E, A, B, C, D, R(41) );
179    P( D, E, A, B, C, R(42) );
180    P( C, D, E, A, B, R(43) );
181    P( B, C, D, E, A, R(44) );
182    P( A, B, C, D, E, R(45) );
183    P( E, A, B, C, D, R(46) );
184    P( D, E, A, B, C, R(47) );
185    P( C, D, E, A, B, R(48) );
186    P( B, C, D, E, A, R(49) );
187    P( A, B, C, D, E, R(50) );
188    P( E, A, B, C, D, R(51) );
189    P( D, E, A, B, C, R(52) );
190    P( C, D, E, A, B, R(53) );
191    P( B, C, D, E, A, R(54) );
192    P( A, B, C, D, E, R(55) );
193    P( E, A, B, C, D, R(56) );
194    P( D, E, A, B, C, R(57) );
195    P( C, D, E, A, B, R(58) );
196    P( B, C, D, E, A, R(59) );
197
198#undef K
199#undef F
200
201#define F(x,y,z) (x ^ y ^ z)
202#define K 0xCA62C1D6
203
204    P( A, B, C, D, E, R(60) );
205    P( E, A, B, C, D, R(61) );
206    P( D, E, A, B, C, R(62) );
207    P( C, D, E, A, B, R(63) );
208    P( B, C, D, E, A, R(64) );
209    P( A, B, C, D, E, R(65) );
210    P( E, A, B, C, D, R(66) );
211    P( D, E, A, B, C, R(67) );
212    P( C, D, E, A, B, R(68) );
213    P( B, C, D, E, A, R(69) );
214    P( A, B, C, D, E, R(70) );
215    P( E, A, B, C, D, R(71) );
216    P( D, E, A, B, C, R(72) );
217    P( C, D, E, A, B, R(73) );
218    P( B, C, D, E, A, R(74) );
219    P( A, B, C, D, E, R(75) );
220    P( E, A, B, C, D, R(76) );
221    P( D, E, A, B, C, R(77) );
222    P( C, D, E, A, B, R(78) );
223    P( B, C, D, E, A, R(79) );
224
225#undef K
226#undef F
227
228    ctx->state[0] += A;
229    ctx->state[1] += B;
230    ctx->state[2] += C;
231    ctx->state[3] += D;
232    ctx->state[4] += E;
233}
234
235/*
236 * SHA-1 process buffer
237 */
238void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
239{
240    size_t fill;
241    unsigned long left;
242
243    if( ilen <= 0 )
244        return;
245
246    left = ctx->total[0] & 0x3F;
247    fill = 64 - left;
248
249    ctx->total[0] += (unsigned long) ilen;
250    ctx->total[0] &= 0xFFFFFFFF;
251
252    if( ctx->total[0] < (unsigned long) ilen )
253        ctx->total[1]++;
254
255    if( left && ilen >= fill )
256    {
257        memcpy( (void *) (ctx->buffer + left),
258                (void *) input, fill );
259        sha1_process( ctx, ctx->buffer );
260        input += fill;
261        ilen  -= fill;
262        left = 0;
263    }
264
265    while( ilen >= 64 )
266    {
267        sha1_process( ctx, input );
268        input += 64;
269        ilen  -= 64;
270    }
271
272    if( ilen > 0 )
273    {
274        memcpy( (void *) (ctx->buffer + left),
275                (void *) input, ilen );
276    }
277}
278
279static const unsigned char sha1_padding[64] =
280{
281 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
282    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
283    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
284    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
285};
286
287/*
288 * SHA-1 final digest
289 */
290void sha1_finish( sha1_context *ctx, unsigned char output[20] )
291{
292    unsigned long last, padn;
293    unsigned long high, low;
294    unsigned char msglen[8];
295
296    high = ( ctx->total[0] >> 29 )
297         | ( ctx->total[1] <<  3 );
298    low  = ( ctx->total[0] <<  3 );
299
300    PUT_ULONG_BE( high, msglen, 0 );
301    PUT_ULONG_BE( low,  msglen, 4 );
302
303    last = ctx->total[0] & 0x3F;
304    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
305
306    sha1_update( ctx, (unsigned char *) sha1_padding, padn );
307    sha1_update( ctx, msglen, 8 );
308
309    PUT_ULONG_BE( ctx->state[0], output,  0 );
310    PUT_ULONG_BE( ctx->state[1], output,  4 );
311    PUT_ULONG_BE( ctx->state[2], output,  8 );
312    PUT_ULONG_BE( ctx->state[3], output, 12 );
313    PUT_ULONG_BE( ctx->state[4], output, 16 );
314}
315
316/*
317 * output = SHA-1( input buffer )
318 */
319void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
320{
321    sha1_context ctx;
322
323    sha1_starts( &ctx );
324    sha1_update( &ctx, input, ilen );
325    sha1_finish( &ctx, output );
326
327    memset( &ctx, 0, sizeof( sha1_context ) );
328}
329
330#if defined(POLARSSL_FS_IO)
331/*
332 * output = SHA-1( file contents )
333 */
334int sha1_file( const char *path, unsigned char output[20] )
335{
336    FILE *f;
337    size_t n;
338    sha1_context ctx;
339    unsigned char buf[1024];
340
341    if( ( f = fopen( path, "rb" ) ) == NULL )
342        return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
343
344    sha1_starts( &ctx );
345
346    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
347        sha1_update( &ctx, buf, n );
348
349    sha1_finish( &ctx, output );
350
351    memset( &ctx, 0, sizeof( sha1_context ) );
352
353    if( ferror( f ) != 0 )
354    {
355        fclose( f );
356        return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
357    }
358
359    fclose( f );
360    return( 0 );
361}
362#endif /* POLARSSL_FS_IO */
363
364/*
365 * SHA-1 HMAC context setup
366 */
367void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
368{
369    size_t i;
370    unsigned char sum[20];
371
372    if( keylen > 64 )
373    {
374        sha1( key, keylen, sum );
375        keylen = 20;
376        key = sum;
377    }
378
379    memset( ctx->ipad, 0x36, 64 );
380    memset( ctx->opad, 0x5C, 64 );
381
382    for( i = 0; i < keylen; i++ )
383    {
384        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
385        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
386    }
387
388    sha1_starts( ctx );
389    sha1_update( ctx, ctx->ipad, 64 );
390
391    memset( sum, 0, sizeof( sum ) );
392}
393
394/*
395 * SHA-1 HMAC process buffer
396 */
397void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
398{
399    sha1_update( ctx, input, ilen );
400}
401
402/*
403 * SHA-1 HMAC final digest
404 */
405void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
406{
407    unsigned char tmpbuf[20];
408
409    sha1_finish( ctx, tmpbuf );
410    sha1_starts( ctx );
411    sha1_update( ctx, ctx->opad, 64 );
412    sha1_update( ctx, tmpbuf, 20 );
413    sha1_finish( ctx, output );
414
415    memset( tmpbuf, 0, sizeof( tmpbuf ) );
416}
417
418/*
419 * SHA1 HMAC context reset
420 */
421void sha1_hmac_reset( sha1_context *ctx )
422{
423    sha1_starts( ctx );
424    sha1_update( ctx, ctx->ipad, 64 );
425}
426
427/*
428 * output = HMAC-SHA-1( hmac key, input buffer )
429 */
430void sha1_hmac( const unsigned char *key, size_t keylen,
431                const unsigned char *input, size_t ilen,
432                unsigned char output[20] )
433{
434    sha1_context ctx;
435
436    sha1_hmac_starts( &ctx, key, keylen );
437    sha1_hmac_update( &ctx, input, ilen );
438    sha1_hmac_finish( &ctx, output );
439
440    memset( &ctx, 0, sizeof( sha1_context ) );
441}
442
443#if defined(POLARSSL_SELF_TEST)
444/*
445 * FIPS-180-1 test vectors
446 */
447static unsigned char sha1_test_buf[3][57] = 
448{
449    { "abc" },
450    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
451    { "" }
452};
453
454static const int sha1_test_buflen[3] =
455{
456    3, 56, 1000
457};
458
459static const unsigned char sha1_test_sum[3][20] =
460{
461    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
462      0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
463    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
464      0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
465    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
466      0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
467};
468
469/*
470 * RFC 2202 test vectors
471 */
472static unsigned char sha1_hmac_test_key[7][26] =
473{
474    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
475      "\x0B\x0B\x0B\x0B" },
476    { "Jefe" },
477    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
478      "\xAA\xAA\xAA\xAA" },
479    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
480      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
481    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
482      "\x0C\x0C\x0C\x0C" },
483    { "" }, /* 0xAA 80 times */
484    { "" }
485};
486
487static const int sha1_hmac_test_keylen[7] =
488{
489    20, 4, 20, 25, 20, 80, 80
490};
491
492static unsigned char sha1_hmac_test_buf[7][74] =
493{
494    { "Hi There" },
495    { "what do ya want for nothing?" },
496    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
497      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
498      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
499      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
500      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
501    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
502      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
503      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
504      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
505      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
506    { "Test With Truncation" },
507    { "Test Using Larger Than Block-Size Key - Hash Key First" },
508    { "Test Using Larger Than Block-Size Key and Larger"
509      " Than One Block-Size Data" }
510};
511
512static const int sha1_hmac_test_buflen[7] =
513{
514    8, 28, 50, 50, 20, 54, 73
515};
516
517static const unsigned char sha1_hmac_test_sum[7][20] =
518{
519    { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
520      0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
521    { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
522      0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
523    { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
524      0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
525    { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
526      0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
527    { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
528      0x7B, 0xE1 },
529    { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
530      0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
531    { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
532      0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
533};
534
535/*
536 * Checkup routine
537 */
538int sha1_self_test( int verbose )
539{
540    int i, j, buflen;
541    unsigned char buf[1024];
542    unsigned char sha1sum[20];
543    sha1_context ctx;
544
545    /*
546     * SHA-1
547     */
548    for( i = 0; i < 3; i++ )
549    {
550        if( verbose != 0 )
551            printf( "  SHA-1 test #%d: ", i + 1 );
552
553        sha1_starts( &ctx );
554
555        if( i == 2 )
556        {
557            memset( buf, 'a', buflen = 1000 );
558
559            for( j = 0; j < 1000; j++ )
560                sha1_update( &ctx, buf, buflen );
561        }
562        else
563            sha1_update( &ctx, sha1_test_buf[i],
564                               sha1_test_buflen[i] );
565
566        sha1_finish( &ctx, sha1sum );
567
568        if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
569        {
570            if( verbose != 0 )
571                printf( "failed\n" );
572
573            return( 1 );
574        }
575
576        if( verbose != 0 )
577            printf( "passed\n" );
578    }
579
580    if( verbose != 0 )
581        printf( "\n" );
582
583    for( i = 0; i < 7; i++ )
584    {
585        if( verbose != 0 )
586            printf( "  HMAC-SHA-1 test #%d: ", i + 1 );
587
588        if( i == 5 || i == 6 )
589        {
590            memset( buf, '\xAA', buflen = 80 );
591            sha1_hmac_starts( &ctx, buf, buflen );
592        }
593        else
594            sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
595                                    sha1_hmac_test_keylen[i] );
596
597        sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
598                                sha1_hmac_test_buflen[i] );
599
600        sha1_hmac_finish( &ctx, sha1sum );
601
602        buflen = ( i == 4 ) ? 12 : 20;
603
604        if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
605        {
606            if( verbose != 0 )
607                printf( "failed\n" );
608
609            return( 1 );
610        }
611
612        if( verbose != 0 )
613            printf( "passed\n" );
614    }
615
616    if( verbose != 0 )
617        printf( "\n" );
618
619    return( 0 );
620}
621
622#endif
623
624#endif
Note: See TracBrowser for help on using the repository browser.

What are you looking for?