/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/ssl_srv.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008-06-24 10:50:29 -0700 (Tue, 24 Jun 2008) $ : Last Committed Date */
00004 /*
00005  *  SSLv3/TLSv1 server-side functions
00006  *
00007  *  Copyright (C) 2006-2007  Christophe Devine
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU Lesser General Public
00011  *  License, version 2.1 as published by the Free Software Foundation.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00021  *  MA  02110-1301  USA
00022  */
00023 
00024 #ifndef _CRT_SECURE_NO_DEPRECATE
00025 #define _CRT_SECURE_NO_DEPRECATE 1
00026 #endif
00027 
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <time.h>
00032 
00033 #include "xyssl/net.h"
00034 #include "xyssl/ssl.h"
00035 
00036 static int ssl_get_session( ssl_context *ssl )
00037 {
00038     time_t t;
00039     int offset;
00040     unsigned char buf[128];
00041     unsigned char hash[20];
00042 
00043     if( ssl->sidtable == NULL || ssl->sidlen != 32 )
00044         return( ERR_SSL_NO_SESSION_FOUND );
00045 
00046     offset = ( (int) ssl->sessid[0] << 8 )
00047            | ( (int) ssl->sessid[1]      );
00048     offset = ( offset % SSL_SESSION_TBL_LEN ) & ~127;
00049 
00050     memcpy( buf, ssl->sidtable + offset, 128 );
00051 
00052     /*
00053      * Accept the session if:
00054      *
00055      *   - the session ID matches
00056      *   - it has not expired yet
00057      *   - the checksum is correct
00058      */
00059     if( memcmp( buf, ssl->sessid, 32 ) != 0 )
00060         return( ERR_SSL_NO_SESSION_FOUND );
00061 
00062     t = ( (time_t) buf[80] << 24 )
00063       | ( (time_t) buf[81] << 16 )
00064       | ( (time_t) buf[82] <<  8 )
00065       | ( (time_t) buf[83]       );
00066 
00067     if( time( NULL ) - t > SSL_EXPIRATION_TIME )
00068         return( ERR_SSL_NO_SESSION_FOUND );
00069 
00070     sha1( buf, 86, hash );
00071     if( memcmp( buf + 86, hash, 20 ) != 0 )
00072         return( ERR_SSL_NO_SESSION_FOUND );
00073 
00074     memcpy( ssl->master, buf + 32, 48 );
00075     ssl->cipher = ( (int) buf[84] << 8 )
00076                 | ( (int) buf[85]      );
00077 
00078     return( 0 );
00079 }
00080 
00081 static void ssl_set_session( ssl_context *ssl )
00082 {
00083     time_t t;
00084     int offset;
00085     unsigned char buf[128];
00086 
00087     if( ssl->sidtable == NULL || ssl->sidlen != 32 )
00088         return;
00089 
00090     /*
00091      *   0  .  31   session ID
00092      *  32  .  79   master key
00093      *  80  .  83   start time
00094      *  84  .  85   chosen cipher
00095      *  86  . 105   SHA1 checksum
00096      */
00097     t = time( NULL );
00098 
00099     memcpy( buf     , ssl->sessid, 32 );
00100     memcpy( buf + 32, ssl->master, 48 );
00101     
00102     buf[80] = (unsigned char)( t >> 24 );
00103     buf[81] = (unsigned char)( t >> 16 );
00104     buf[82] = (unsigned char)( t >>  8 );
00105     buf[83] = (unsigned char)( t       );
00106 
00107     buf[84] = ( ssl->cipher >> 8 );
00108     buf[85] = ( ssl->cipher      );
00109 
00110     sha1( buf, 86, buf + 86 );
00111 
00112     offset = ( (int) ssl->sessid[0] << 8 )
00113            | ( (int) ssl->sessid[1]      );
00114     offset = ( offset % SSL_SESSION_TBL_LEN ) & ~127;
00115 
00116     memcpy( ssl->sidtable + offset, buf, 128 );
00117 }
00118 
00119 static int ssl_parse_client_hello( ssl_context *ssl )
00120 {
00121     int ret, i, j, n;
00122     int ciph_len, sess_len;
00123     int chal_len, comp_len;
00124     unsigned char *buf, *p;
00125 
00126     buf = ssl->in_hdr;
00127 
00128     if( ssl->in_left < 5 )
00129     {
00130         /*
00131          * Handle partial reads, for non-blocking sockets
00132          */
00133         n = 5 - ssl->in_left;
00134         ret = net_recv( ssl->read_fd, buf + ssl->in_left, &n );
00135         ssl->in_left += n;
00136 
00137         if( ret != 0 )
00138             return( ret );
00139     }
00140 
00141     if( ( buf[0] & 0x80 ) != 0 )
00142     {
00143         /*
00144          * SSLv2 Client Hello
00145          *
00146          * Record layer:
00147          *     0  .   1   message length
00148          *
00149          * SSL layer:
00150          *     2  .   2   message type
00151          *     3  .   4   protocol version
00152          */
00153         if( buf[0] != 0x80 || buf[1] < 17 ||
00154             buf[2] != SSL_HS_CLIENT_HELLO ||
00155             buf[3] != SSLV3_MAJOR_VERSION )
00156             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00157 
00158         memcpy( ssl->max_ver, buf + 3, 2 );
00159 
00160         ssl->major_ver = SSLV3_MAJOR_VERSION;
00161         ssl->minor_ver = ( buf[4] <= TLS10_MINOR_VERSION )
00162                          ? buf[4]  : TLS10_MINOR_VERSION;
00163 
00164         n = (int) buf[1] - 3;
00165 
00166         if( ssl->in_left < 5 + n )
00167         {
00168             n -= ssl->in_left - 5;
00169             ret = net_recv( ssl->read_fd, buf + ssl->in_left, &n );
00170             ssl->in_left += n;
00171 
00172             if( ret != 0 )
00173                 return( ret );
00174         }
00175 
00176         md5_starts( &ssl->hs_md5 );
00177         md5_update( &ssl->hs_md5, buf + 2, (int) buf[1] );
00178 
00179         sha1_starts( &ssl->hs_sha1 );
00180         sha1_update( &ssl->hs_sha1, buf + 2, (int) buf[1] );
00181 
00182         buf = ssl->in_msg;
00183         n = ssl->in_left - 5;
00184 
00185         /*
00186          *    0  .   1   cipherlist length
00187          *    2  .   3   session id length
00188          *    4  .   5   challenge length
00189          *    6  .  ..   cipherlist
00190          *   ..  .  ..   session id
00191          *   ..  .  ..   challenge
00192          */
00193         ciph_len = ( (int) buf[0] << 8 ) | (int) buf[1];
00194         sess_len = ( (int) buf[2] << 8 ) | (int) buf[3];
00195         chal_len = ( (int) buf[4] << 8 ) | (int) buf[5];
00196 
00197         if(   ciph_len < 3 || ciph_len > 192 ||
00198             ( ciph_len % 3 ) != 0 )
00199             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00200 
00201         if( sess_len < 0 || sess_len > 32 )
00202             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00203 
00204         if( chal_len < 8 || chal_len > 32 )
00205             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00206 
00207         if( n != 6 + ciph_len + sess_len + chal_len )
00208             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00209 
00210         p = buf + 6 + ciph_len;
00211         memset( ssl->randbytes, 0, 64 );
00212         memcpy( ssl->randbytes + 32 - chal_len, p, chal_len );
00213 
00214         p += sess_len;
00215         ssl->sidlen = sess_len;
00216         memcpy( ssl->sessid, p, sess_len );
00217 
00218         for( i = 0; ssl->cipherlist[i] != 0; i++ )
00219         {
00220             for( j = 0, p = buf + 6; j < ciph_len;
00221                 j += 3, p += 3 )
00222             {
00223                 if( p[0] == 0 && p[1] == 0 &&
00224                     p[2] == ssl->cipherlist[i] )
00225                     goto have_cipher;
00226             }
00227         }
00228     }
00229     else
00230     {
00231         /*
00232          * SSLv3 Client Hello
00233          *
00234          * Record layer:
00235          *     0  .   0   message type
00236          *     1  .   2   protocol version
00237          *     3  .   4   message length
00238          */
00239         if( buf[0] != SSL_MSG_HANDSHAKE   ||
00240             buf[1] != SSLV3_MAJOR_VERSION ||
00241             buf[3] != 0 || buf[4] < 45 )
00242             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00243 
00244         n = (int) buf[4];
00245 
00246         if( ssl->in_left < 5 + n )
00247         {
00248             n -= ( ssl->in_left - 5 );
00249             ret = net_recv( ssl->read_fd, buf + ssl->in_left, &n );
00250             ssl->in_left += n;
00251 
00252             if( ret != 0 )
00253                 return( ret );
00254         }
00255 
00256         buf = ssl->in_msg;
00257         n = ssl->in_left - 5;
00258 
00259         md5_starts( &ssl->hs_md5 );
00260         md5_update( &ssl->hs_md5, buf, n );
00261 
00262         sha1_starts( &ssl->hs_sha1 );
00263         sha1_update( &ssl->hs_sha1, buf, n );
00264 
00265         /*
00266          * SSL layer:
00267          *     0  .   0   handshake type
00268          *     1  .   3   handshake length
00269          *     4  .   5   protocol version
00270          *     6  .   9   UNIX time()
00271          *    10  .  37   random bytes
00272          *    38  .  38   session id length
00273          *    39  . 38+x  session id
00274          *   39+x . 40+x  cipherlist length
00275          *   41+x .  ..   cipherlist
00276          *    ..  .  ..   compression alg.
00277          */
00278 
00279         /* check the protocol version */
00280         if( buf[0] != SSL_HS_CLIENT_HELLO ||
00281             buf[4] != SSLV3_MAJOR_VERSION )
00282             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00283 
00284         ssl->major_ver = SSLV3_MAJOR_VERSION;
00285         ssl->minor_ver = ( buf[5] <= TLS10_MINOR_VERSION )
00286                          ? buf[5]  : TLS10_MINOR_VERSION;
00287 
00288         memcpy( ssl->max_ver  , buf + 4,  2 );
00289         memcpy( ssl->randbytes, buf + 6, 32 );
00290 
00291         /* check the message length */
00292         if( buf[1] != 0 || buf[2] != 0 || (int) buf[3] + 4 != n )
00293             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00294 
00295         /* check the session length */
00296         sess_len = (int) buf[38];
00297 
00298         if( sess_len < 0 || sess_len > 32 )
00299             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00300 
00301         ssl->sidlen = sess_len;
00302         memcpy( ssl->sessid, buf + 39, ssl->sidlen );
00303 
00304         /* check the cipherlist length */
00305         ciph_len = (int) buf[40 + sess_len];
00306 
00307         if(   ciph_len < 2 || ciph_len > 128 ||
00308             ( ciph_len % 2 ) != 0 )
00309             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00310 
00311         /* check the compression alg. length */
00312         comp_len = (int) buf[41 + sess_len + ciph_len];
00313 
00314         if( n != 42 + sess_len + ciph_len + comp_len )
00315             return( ERR_SSL_BAD_HS_CLIENT_HELLO );
00316 
00317         /* search for a matching cipher */
00318         for( i = 0; ssl->cipherlist[i] != 0; i++ )
00319         {
00320             for( j = 0, p = buf + 41 + sess_len; j < ciph_len;
00321                 j += 2, p += 2 )
00322             {
00323                 if( p[0] == 0 && p[1] == ssl->cipherlist[i] )
00324                     goto have_cipher;
00325             }
00326         }
00327     }
00328 
00329     return( ERR_SSL_NO_CIPHER_CHOSEN );
00330 
00331 have_cipher:
00332 
00333     ssl->cipher  = ssl->cipherlist[i];
00334     ssl->in_left = 0;
00335     ssl->state++;
00336     return( 0 );
00337 }
00338 
00339 static int ssl_write_server_hello( ssl_context *ssl )
00340 {
00341     int i;
00342     time_t t;
00343     unsigned char *buf, *p;
00344 
00345     /*
00346      *     0  .   0   handshake type
00347      *     1  .   3   handshake length
00348      *     4  .   5   protocol version
00349      *     6  .   9   UNIX time()
00350      *    10  .  37   random bytes
00351      */
00352     buf = ssl->out_msg;
00353     p = buf + 4;
00354 
00355     *p++ = ssl->major_ver;
00356     *p++ = ssl->minor_ver;
00357 
00358     t = time( NULL );
00359     *p++ = (unsigned char)( t >> 24 );
00360     *p++ = (unsigned char)( t >> 16 );
00361     *p++ = (unsigned char)( t >>  8 );
00362     *p++ = (unsigned char)( t       );
00363 
00364     for( i = 28; i > 0; i-- )
00365         *p++ = ssl->rng_f( ssl->rng_d );
00366 
00367     memcpy( ssl->randbytes + 32, buf + 6, 32 );
00368 
00369     /*
00370      *    38  .  38   session id length
00371      *    39  . 38+x  session id
00372      *   39+x . 40+x  chosen cipher
00373      *   41+x . 41+x  chosen compression alg.
00374      */
00375     *p++ = ssl->sidlen = 32;
00376 
00377     if( ssl_get_session( ssl ) == 0 )
00378     {
00379         /*
00380          * Found a matching session, resume it
00381          */
00382         ssl->resumed = 1;
00383         ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
00384         ssl_derive_keys( ssl );
00385     }
00386     else
00387     {
00388         ssl->resumed = 0;
00389         ssl->state++;
00390 
00391         for( i = 0; i < ssl->sidlen; i++ )
00392             ssl->sessid[i] = ssl->rng_f( ssl->rng_d );
00393     }
00394 
00395     memcpy( p, ssl->sessid, ssl->sidlen );
00396     p += ssl->sidlen;
00397 
00398     *p++ = 0;
00399     *p++ = ssl->cipher;
00400     *p++ = SSL_COMPRESS_NULL;
00401 
00402     ssl->out_msglen  = p - buf;
00403     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
00404     ssl->out_msg[0]  = SSL_HS_SERVER_HELLO;
00405 
00406     return( ssl_write_record( ssl, 0 ) );
00407 }
00408 
00409 static int ssl_write_certificate_request( ssl_context *ssl )
00410 {
00411     int n;
00412     unsigned char *buf, *p;
00413     x509_cert *crt;
00414 
00415     ssl->state++;
00416 
00417     if( ssl->authmode == SSL_VERIFY_NONE )
00418         return( 0 );
00419 
00420     /*
00421      *     0  .   0   handshake type
00422      *     1  .   3   handshake length
00423      *     4  .   4   cert type count
00424      *     5  .. n-1  cert types
00425      *     n  .. n+1  length of all DNs
00426      *    n+2 .. n+3  length of DN 1
00427      *    n+4 .. ...  Distinguished Name #1
00428      *    ... .. ...  length of DN 2, etc.
00429      */
00430     buf = ssl->out_msg;
00431     p = buf + 4;
00432 
00433     *p++ = 1;
00434     *p++ = 1;   /* RSA sign */
00435 
00436     p += 2;
00437     crt = ssl->ca_chain;
00438 
00439     while( crt != NULL && crt->next != NULL )
00440     {
00441         if( p - buf > 4096 )
00442             break;
00443 
00444         n = crt->subject_raw.len;
00445         *p++ = ( n >> 8 );
00446         *p++ = ( n      );
00447 
00448         memcpy( p, crt->subject_raw.p, n );
00449         p += n;
00450 
00451         crt = crt->next;
00452     }
00453 
00454     ssl->out_msglen  = n = p - buf;
00455     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
00456     ssl->out_msg[0]  = SSL_HS_CERTIFICATE_REQUEST;
00457     ssl->out_msg[6]  = ( (n - 8) >> 8 );
00458     ssl->out_msg[7]  = ( (n - 8)      );
00459 
00460     return( ssl_write_record( ssl, 0 ) );
00461 }
00462 
00463 static int ssl_write_server_key_exchange( ssl_context *ssl )
00464 {
00465     int ret, n;
00466     unsigned char hash[36];
00467     md5_context md5;
00468     sha1_context sha1;
00469 
00470     if( ssl->cipher != SSL3_EDH_RSA_DES_168_SHA &&
00471         ssl->cipher != TLS1_EDH_RSA_AES_256_SHA )
00472     {
00473         ssl->state++;
00474         return( 0 );
00475     }
00476 
00477 #if defined(NO_DHM)
00478     return( ERR_SSL_FEATURE_UNAVAILABLE );
00479 #else
00480     /*
00481      * Ephemeral DH parameters:
00482      *
00483      * struct {
00484      *     opaque dh_p<1..2^16-1>;
00485      *     opaque dh_g<1..2^16-1>;
00486      *     opaque dh_Ys<1..2^16-1>;
00487      * } ServerDHParams;
00488      */
00489     if( ( ret = dhm_make_params( &ssl->dhm_ctx, ssl->rng_f,
00490                       ssl->rng_d, ssl->out_msg + 4, &n ) ) != 0 )
00491         return( ret );
00492 
00493     /*
00494      * digitally-signed struct {
00495      *     opaque md5_hash[16];
00496      *     opaque sha_hash[20];
00497      * };
00498      *
00499      * md5_hash
00500      *     MD5(ClientHello.random + ServerHello.random
00501      *                            + ServerParams);
00502      * sha_hash
00503      *     SHA(ClientHello.random + ServerHello.random
00504      *                            + ServerParams);
00505      */
00506     md5_starts( &md5 );
00507     md5_update( &md5, ssl->randbytes,  64 );
00508     md5_update( &md5, ssl->out_msg + 4, n );
00509     md5_finish( &md5, hash );
00510 
00511     sha1_starts( &sha1 );
00512     sha1_update( &sha1, ssl->randbytes,  64 );
00513     sha1_update( &sha1, ssl->out_msg + 4, n );
00514     sha1_finish( &sha1, hash + 16 );
00515 
00516     ssl->out_msg[4 + n] = ( ssl->own_key->len >> 8 );
00517     ssl->out_msg[5 + n] = ( ssl->own_key->len      );
00518 
00519     if( ( ret = rsa_pkcs1_sign( ssl->own_key, RSA_RAW,
00520                                 hash, 36, ssl->out_msg + 6 + n,
00521                                 ssl->own_key->len ) ) != 0 )
00522         return( ret );
00523 
00524     ssl->out_msglen  = 6 + n + ssl->own_key->len;
00525     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
00526     ssl->out_msg[0]  = SSL_HS_SERVER_KEY_EXCHANGE;
00527 
00528     ssl->state++;
00529     return( ssl_write_record( ssl, 0 ) );
00530 #endif
00531 }
00532 
00533 static int ssl_write_server_hello_done( ssl_context *ssl )
00534 {
00535     ssl->out_msglen  = 4;
00536     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
00537     ssl->out_msg[0]  = SSL_HS_SERVER_HELLO_DONE;
00538 
00539     ssl->state++;
00540     return( ssl_write_record( ssl, 0 ) );
00541 }
00542 
00543 static int ssl_parse_client_key_exchange( ssl_context *ssl )
00544 {
00545     int ret, i, n;
00546 
00547     if( ( ret = ssl_read_record( ssl, 0 ) ) != 0 )
00548         return( ret );
00549 
00550     if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
00551         return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
00552 
00553     if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE )
00554         return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
00555 
00556     if( ssl->cipher == SSL3_EDH_RSA_DES_168_SHA ||
00557         ssl->cipher == TLS1_EDH_RSA_AES_256_SHA )
00558     {
00559 #if defined(NO_DHM)
00560         return( ERR_SSL_FEATURE_UNAVAILABLE );
00561 #else
00562         /*
00563          * Receive G^Y mod P, premaster = (G^Y)^X mod P
00564          */
00565         n = ( ssl->in_msg[4] << 8 )
00566           | ( ssl->in_msg[5]      );
00567 
00568         if( n < 1 || n > ssl->dhm_ctx.len ||
00569             n + 6 != ssl->in_hslen )
00570             return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
00571 
00572         if( ( ret = dhm_read_public( &ssl->dhm_ctx,
00573                                       ssl->in_msg + 6, n ) ) != 0 )
00574             return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE | ret );
00575 
00576         ssl->pmslen = ssl->dhm_ctx.len;
00577 
00578         if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
00579                                       ssl->premaster,
00580                                      &ssl->pmslen ) ) != 0 )
00581             return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE | ret );
00582 #endif
00583     }
00584     else
00585     {
00586         /*
00587          * Decrypt the premaster using own private RSA key
00588          */
00589         i = 4;
00590         n = ssl->own_key->len;
00591         ssl->pmslen = 48;
00592 
00593         if( ssl->minor_ver != SSLV3_MINOR_VERSION )
00594         {
00595             i += 2;
00596             if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) ||
00597                 ssl->in_msg[5] != ( ( n      ) & 0xFF ) )
00598                 return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
00599         }
00600 
00601         if( ssl->in_hslen != i + n )
00602             return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
00603 
00604         ret = rsa_pkcs1_decrypt( ssl->own_key,
00605                                  ssl->in_msg + i, n,
00606                                  ssl->premaster,
00607                                 &ssl->pmslen );
00608 
00609         if( ret != 0 )
00610             return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE | ret );
00611 
00612         if( ssl->pmslen != 48 ||
00613             memcmp( ssl->premaster, ssl->max_ver, 2 ) != 0 )
00614             return( ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
00615     }
00616 
00617     ssl_derive_keys( ssl );
00618     ssl_set_session( ssl );
00619 
00620     ssl->state++;
00621     return( 0 );
00622 }
00623 
00624 static int ssl_parse_certificate_verify( ssl_context *ssl )
00625 {
00626     int n1, n2, ret;
00627     unsigned char hash[36];
00628 
00629     if( ssl->peer_cert == NULL )
00630     {
00631         ssl->state++;
00632         return( 0 );
00633     }
00634 
00635     ssl_calc_verify( ssl, hash );
00636 
00637     if( ( ret = ssl_read_record( ssl, 0 ) ) != 0 )
00638         return( ret );
00639 
00640     if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
00641         return( ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
00642 
00643     if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY )
00644         return( ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
00645 
00646     n1 = ssl->peer_cert->rsa.len;
00647     n2 = ( (int) ssl->in_msg[4] << 8 )
00648        | ( (int) ssl->in_msg[5]      );
00649 
00650     if( n1 + 6 != ssl->in_hslen || n1 != n2 )
00651         return( ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
00652 
00653     ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa,
00654                             RSA_RAW, hash, 36,
00655                             ssl->in_msg + 6, n1 );
00656 
00657     ssl->state++;
00658     return( ( ssl->authmode == SSL_VERIFY_REQUIRED ) ? ret : 0 );
00659 }
00660 
00661 static const char _ssl_srv_src[] = "_ssl_srv_src";
00662 
00663 /*
00664  * SSL handshake -- server side
00665  */
00666 int ssl_server_start( ssl_context *ssl )
00667 {
00668     int ret = ssl_flush_output( ssl );
00669 
00670     while( ret == 0 )
00671     {
00672         switch( ssl->state )
00673         {
00674         case SSL_HELLO_REQUEST:
00675             ssl->state = SSL_CLIENT_HELLO;
00676             break;
00677 
00678         /*
00679          *  <==   ClientHello
00680          */
00681         case SSL_CLIENT_HELLO:
00682             ret = ssl_parse_client_hello( ssl );
00683             break;
00684 
00685         /*
00686          *  ==>   ServerHello
00687          *        Certificate
00688          *      ( ServerKeyExchange  )
00689          *      ( CertificateRequest )
00690          *        ServerHelloDone
00691          */
00692         case SSL_SERVER_HELLO:
00693             ret = ssl_write_server_hello( ssl );
00694             break;
00695 
00696         case SSL_SERVER_CERTIFICATE:
00697             ret = ssl_write_certificate( ssl );
00698             break;
00699 
00700         case SSL_SERVER_KEY_EXCHANGE:
00701             ret = ssl_write_server_key_exchange( ssl );
00702             break;
00703 
00704         case SSL_CERTIFICATE_REQUEST:
00705             ret = ssl_write_certificate_request( ssl );
00706             break;
00707 
00708         case SSL_SERVER_HELLO_DONE:
00709             ret = ssl_write_server_hello_done( ssl );
00710             break;
00711 
00712         /*
00713          *  <== ( Certificate/Alert  )
00714          *        ClientKeyExchange
00715          *      ( CertificateVerify  )
00716          *        ChangeCipherSpec
00717          *        Finished
00718          */
00719         case SSL_CLIENT_CERTIFICATE:
00720             ret = ssl_parse_certificate( ssl );
00721             break;
00722 
00723         case SSL_CLIENT_KEY_EXCHANGE:
00724             ret = ssl_parse_client_key_exchange( ssl );
00725             break;
00726 
00727         case SSL_CERTIFICATE_VERIFY:
00728             ret = ssl_parse_certificate_verify( ssl );
00729             break;
00730 
00731         case SSL_CLIENT_CHANGE_CIPHER_SPEC:
00732             ret = ssl_parse_change_cipher_spec( ssl );
00733             break;
00734 
00735         case SSL_CLIENT_FINISHED:
00736             ret = ssl_parse_finished( ssl );
00737             break;
00738 
00739         /*
00740          *  ==>   ChangeCipherSpec
00741          *        Finished
00742          */
00743         case SSL_SERVER_CHANGE_CIPHER_SPEC:
00744             ret = ssl_write_change_cipher_spec( ssl );
00745             break;
00746 
00747         case SSL_SERVER_FINISHED:
00748             ret = ssl_write_finished( ssl );
00749             break;
00750 
00751         default:
00752             return( 0 );
00753         }
00754     }
00755 
00756     return( ret );
00757 }

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4