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

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

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4