1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libssl/src/s2_clnt.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1138 @@
1.4 +/* ssl/s2_clnt.c */
1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
1.6 + * All rights reserved.
1.7 + *
1.8 + * This package is an SSL implementation written
1.9 + * by Eric Young (eay@cryptsoft.com).
1.10 + * The implementation was written so as to conform with Netscapes SSL.
1.11 + *
1.12 + * This library is free for commercial and non-commercial use as long as
1.13 + * the following conditions are aheared to. The following conditions
1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
1.15 + * lhash, DES, etc., code; not just the SSL code. The SSL documentation
1.16 + * included with this distribution is covered by the same copyright terms
1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1.18 + *
1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
1.20 + * the code are not to be removed.
1.21 + * If this package is used in a product, Eric Young should be given attribution
1.22 + * as the author of the parts of the library used.
1.23 + * This can be in the form of a textual message at program startup or
1.24 + * in documentation (online or textual) provided with the package.
1.25 + *
1.26 + * Redistribution and use in source and binary forms, with or without
1.27 + * modification, are permitted provided that the following conditions
1.28 + * are met:
1.29 + * 1. Redistributions of source code must retain the copyright
1.30 + * notice, this list of conditions and the following disclaimer.
1.31 + * 2. Redistributions in binary form must reproduce the above copyright
1.32 + * notice, this list of conditions and the following disclaimer in the
1.33 + * documentation and/or other materials provided with the distribution.
1.34 + * 3. All advertising materials mentioning features or use of this software
1.35 + * must display the following acknowledgement:
1.36 + * "This product includes cryptographic software written by
1.37 + * Eric Young (eay@cryptsoft.com)"
1.38 + * The word 'cryptographic' can be left out if the rouines from the library
1.39 + * being used are not cryptographic related :-).
1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from
1.41 + * the apps directory (application code) you must include an acknowledgement:
1.42 + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
1.43 + *
1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.47 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.54 + * SUCH DAMAGE.
1.55 + *
1.56 + * The licence and distribution terms for any publically available version or
1.57 + * derivative of this code cannot be changed. i.e. this code cannot simply be
1.58 + * copied and put under another distribution licence
1.59 + * [including the GNU Public Licence.]
1.60 + */
1.61 +/* ====================================================================
1.62 + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
1.63 + *
1.64 + * Redistribution and use in source and binary forms, with or without
1.65 + * modification, are permitted provided that the following conditions
1.66 + * are met:
1.67 + *
1.68 + * 1. Redistributions of source code must retain the above copyright
1.69 + * notice, this list of conditions and the following disclaimer.
1.70 + *
1.71 + * 2. Redistributions in binary form must reproduce the above copyright
1.72 + * notice, this list of conditions and the following disclaimer in
1.73 + * the documentation and/or other materials provided with the
1.74 + * distribution.
1.75 + *
1.76 + * 3. All advertising materials mentioning features or use of this
1.77 + * software must display the following acknowledgment:
1.78 + * "This product includes software developed by the OpenSSL Project
1.79 + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
1.80 + *
1.81 + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
1.82 + * endorse or promote products derived from this software without
1.83 + * prior written permission. For written permission, please contact
1.84 + * openssl-core@openssl.org.
1.85 + *
1.86 + * 5. Products derived from this software may not be called "OpenSSL"
1.87 + * nor may "OpenSSL" appear in their names without prior written
1.88 + * permission of the OpenSSL Project.
1.89 + *
1.90 + * 6. Redistributions of any form whatsoever must retain the following
1.91 + * acknowledgment:
1.92 + * "This product includes software developed by the OpenSSL Project
1.93 + * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
1.94 + *
1.95 + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
1.96 + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.97 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1.98 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
1.99 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1.100 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1.101 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1.102 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.103 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1.104 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1.105 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1.106 + * OF THE POSSIBILITY OF SUCH DAMAGE.
1.107 + * ====================================================================
1.108 + *
1.109 + * This product includes cryptographic software written by Eric Young
1.110 + * (eay@cryptsoft.com). This product includes software written by Tim
1.111 + * Hudson (tjh@cryptsoft.com).
1.112 + *
1.113 + */
1.114 +/*
1.115 + © Portions copyright (c) 2006 Nokia Corporation. All rights reserved.
1.116 + */
1.117 +
1.118 +#include "ssl_locl.h"
1.119 +#ifndef OPENSSL_NO_SSL2
1.120 +#include <stdio.h>
1.121 +#include <openssl/rand.h>
1.122 +#include <openssl/buffer.h>
1.123 +#include <openssl/objects.h>
1.124 +#include <openssl/evp.h>
1.125 +
1.126 +#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
1.127 +#include "libssl_wsd.h"
1.128 +#endif
1.129 +
1.130 +
1.131 +#ifdef EMULATOR
1.132 +
1.133 + GET_STATIC_VAR_FROM_TLS(SSLv2_client_method_data,s2_clnt,SSL_METHOD)
1.134 +
1.135 + #define SSLv2_client_method_data (*GET_WSD_VAR_NAME(SSLv2_client_method_data,s2_clnt,s)())
1.136 +
1.137 +#endif
1.138 +static SSL_METHOD *ssl2_get_client_method(int ver);
1.139 +static int get_server_finished(SSL *s);
1.140 +static int get_server_verify(SSL *s);
1.141 +static int get_server_hello(SSL *s);
1.142 +static int client_hello(SSL *s);
1.143 +static int client_master_key(SSL *s);
1.144 +static int client_finished(SSL *s);
1.145 +static int client_certificate(SSL *s);
1.146 +static int ssl_rsa_public_encrypt(SESS_CERT *sc, int len, unsigned char *from,
1.147 + unsigned char *to,int padding);
1.148 +#define BREAK break
1.149 +
1.150 +static SSL_METHOD *ssl2_get_client_method(int ver)
1.151 + {
1.152 + if (ver == SSL2_VERSION)
1.153 + return(SSLv2_client_method());
1.154 + else
1.155 + return(NULL);
1.156 + }
1.157 +
1.158 +EXPORT_C IMPLEMENT_ssl2_meth_func(SSLv2_client_method,
1.159 + ssl_undefined_function,
1.160 + ssl2_connect,
1.161 + ssl2_get_client_method)
1.162 +
1.163 +int ssl2_connect(SSL *s)
1.164 + {
1.165 + unsigned long l=(unsigned long)time(NULL);
1.166 + BUF_MEM *buf=NULL;
1.167 + int ret= -1;
1.168 + void (*cb)(const SSL *ssl,int type,int val)=NULL;
1.169 + int new_state,state;
1.170 +
1.171 + RAND_add(&l,sizeof(l),0);
1.172 + ERR_clear_error();
1.173 + clear_sys_error();
1.174 +
1.175 + if (s->info_callback != NULL)
1.176 + cb=s->info_callback;
1.177 + else if (s->ctx->info_callback != NULL)
1.178 + cb=s->ctx->info_callback;
1.179 +
1.180 + /* init things to blank */
1.181 + s->in_handshake++;
1.182 + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
1.183 +
1.184 + for (;;)
1.185 + {
1.186 + state=s->state;
1.187 +
1.188 + switch (s->state)
1.189 + {
1.190 + case SSL_ST_BEFORE:
1.191 + case SSL_ST_CONNECT:
1.192 + case SSL_ST_BEFORE|SSL_ST_CONNECT:
1.193 + case SSL_ST_OK|SSL_ST_CONNECT:
1.194 +
1.195 + s->server=0;
1.196 + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
1.197 +
1.198 + s->version=SSL2_VERSION;
1.199 + s->type=SSL_ST_CONNECT;
1.200 +
1.201 + buf=s->init_buf;
1.202 + if ((buf == NULL) && ((buf=BUF_MEM_new()) == NULL))
1.203 + {
1.204 + ret= -1;
1.205 + goto end;
1.206 + }
1.207 + if (!BUF_MEM_grow(buf,
1.208 + SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
1.209 + {
1.210 + if (buf == s->init_buf)
1.211 + buf=NULL;
1.212 + ret= -1;
1.213 + goto end;
1.214 + }
1.215 + s->init_buf=buf;
1.216 + buf=NULL;
1.217 + s->init_num=0;
1.218 + s->state=SSL2_ST_SEND_CLIENT_HELLO_A;
1.219 + s->ctx->stats.sess_connect++;
1.220 + s->handshake_func=ssl2_connect;
1.221 + BREAK;
1.222 +
1.223 + case SSL2_ST_SEND_CLIENT_HELLO_A:
1.224 + case SSL2_ST_SEND_CLIENT_HELLO_B:
1.225 + s->shutdown=0;
1.226 + ret=client_hello(s);
1.227 + if (ret <= 0) goto end;
1.228 + s->init_num=0;
1.229 + s->state=SSL2_ST_GET_SERVER_HELLO_A;
1.230 + BREAK;
1.231 +
1.232 + case SSL2_ST_GET_SERVER_HELLO_A:
1.233 + case SSL2_ST_GET_SERVER_HELLO_B:
1.234 + ret=get_server_hello(s);
1.235 + if (ret <= 0) goto end;
1.236 + s->init_num=0;
1.237 + if (!s->hit) /* new session */
1.238 + {
1.239 + s->state=SSL2_ST_SEND_CLIENT_MASTER_KEY_A;
1.240 + BREAK;
1.241 + }
1.242 + else
1.243 + {
1.244 + s->state=SSL2_ST_CLIENT_START_ENCRYPTION;
1.245 + break;
1.246 + }
1.247 +
1.248 + case SSL2_ST_SEND_CLIENT_MASTER_KEY_A:
1.249 + case SSL2_ST_SEND_CLIENT_MASTER_KEY_B:
1.250 + ret=client_master_key(s);
1.251 + if (ret <= 0) goto end;
1.252 + s->init_num=0;
1.253 + s->state=SSL2_ST_CLIENT_START_ENCRYPTION;
1.254 + break;
1.255 +
1.256 + case SSL2_ST_CLIENT_START_ENCRYPTION:
1.257 + /* Ok, we now have all the stuff needed to
1.258 + * start encrypting, so lets fire it up :-) */
1.259 + if (!ssl2_enc_init(s,1))
1.260 + {
1.261 + ret= -1;
1.262 + goto end;
1.263 + }
1.264 + s->s2->clear_text=0;
1.265 + s->state=SSL2_ST_SEND_CLIENT_FINISHED_A;
1.266 + break;
1.267 +
1.268 + case SSL2_ST_SEND_CLIENT_FINISHED_A:
1.269 + case SSL2_ST_SEND_CLIENT_FINISHED_B:
1.270 + ret=client_finished(s);
1.271 + if (ret <= 0) goto end;
1.272 + s->init_num=0;
1.273 + s->state=SSL2_ST_GET_SERVER_VERIFY_A;
1.274 + break;
1.275 +
1.276 + case SSL2_ST_GET_SERVER_VERIFY_A:
1.277 + case SSL2_ST_GET_SERVER_VERIFY_B:
1.278 + ret=get_server_verify(s);
1.279 + if (ret <= 0) goto end;
1.280 + s->init_num=0;
1.281 + s->state=SSL2_ST_GET_SERVER_FINISHED_A;
1.282 + break;
1.283 +
1.284 + case SSL2_ST_GET_SERVER_FINISHED_A:
1.285 + case SSL2_ST_GET_SERVER_FINISHED_B:
1.286 + ret=get_server_finished(s);
1.287 + if (ret <= 0) goto end;
1.288 + break;
1.289 +
1.290 + case SSL2_ST_SEND_CLIENT_CERTIFICATE_A:
1.291 + case SSL2_ST_SEND_CLIENT_CERTIFICATE_B:
1.292 + case SSL2_ST_SEND_CLIENT_CERTIFICATE_C:
1.293 + case SSL2_ST_SEND_CLIENT_CERTIFICATE_D:
1.294 + case SSL2_ST_X509_GET_CLIENT_CERTIFICATE:
1.295 + ret=client_certificate(s);
1.296 + if (ret <= 0) goto end;
1.297 + s->init_num=0;
1.298 + s->state=SSL2_ST_GET_SERVER_FINISHED_A;
1.299 + break;
1.300 +
1.301 + case SSL_ST_OK:
1.302 + if (s->init_buf != NULL)
1.303 + {
1.304 + BUF_MEM_free(s->init_buf);
1.305 + s->init_buf=NULL;
1.306 + }
1.307 + s->init_num=0;
1.308 + /* ERR_clear_error();*/
1.309 +
1.310 + /* If we want to cache session-ids in the client
1.311 + * and we successfully add the session-id to the
1.312 + * cache, and there is a callback, then pass it out.
1.313 + * 26/11/96 - eay - only add if not a re-used session.
1.314 + */
1.315 +
1.316 + ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
1.317 + if (s->hit) s->ctx->stats.sess_hit++;
1.318 +
1.319 + ret=1;
1.320 + /* s->server=0; */
1.321 + s->ctx->stats.sess_connect_good++;
1.322 +
1.323 + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
1.324 +
1.325 + goto end;
1.326 + /* break; */
1.327 + default:
1.328 + SSLerr(SSL_F_SSL2_CONNECT,SSL_R_UNKNOWN_STATE);
1.329 + return(-1);
1.330 + /* break; */
1.331 + }
1.332 +
1.333 + if ((cb != NULL) && (s->state != state))
1.334 + {
1.335 + new_state=s->state;
1.336 + s->state=state;
1.337 + cb(s,SSL_CB_CONNECT_LOOP,1);
1.338 + s->state=new_state;
1.339 + }
1.340 + }
1.341 +end:
1.342 + s->in_handshake--;
1.343 + if (buf != NULL)
1.344 + BUF_MEM_free(buf);
1.345 + if (cb != NULL)
1.346 + cb(s,SSL_CB_CONNECT_EXIT,ret);
1.347 + return(ret);
1.348 + }
1.349 +
1.350 +static int get_server_hello(SSL *s)
1.351 + {
1.352 + unsigned char *buf;
1.353 + unsigned char *p;
1.354 + int i,j;
1.355 + unsigned long len;
1.356 + STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow;
1.357 +
1.358 + buf=(unsigned char *)s->init_buf->data;
1.359 + p=buf;
1.360 + if (s->state == SSL2_ST_GET_SERVER_HELLO_A)
1.361 + {
1.362 + i=ssl2_read(s,(char *)&(buf[s->init_num]),11-s->init_num);
1.363 + if (i < (11-s->init_num))
1.364 + return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
1.365 + s->init_num = 11;
1.366 +
1.367 + if (*(p++) != SSL2_MT_SERVER_HELLO)
1.368 + {
1.369 + if (p[-1] != SSL2_MT_ERROR)
1.370 + {
1.371 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.372 + SSLerr(SSL_F_GET_SERVER_HELLO,
1.373 + SSL_R_READ_WRONG_PACKET_TYPE);
1.374 + }
1.375 + else
1.376 + SSLerr(SSL_F_GET_SERVER_HELLO,
1.377 + SSL_R_PEER_ERROR);
1.378 + return(-1);
1.379 + }
1.380 +#ifdef __APPLE_CC__
1.381 + /* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug
1.382 + * workaround. <appro@fy.chalmers.se> */
1.383 + s->hit=(i=*(p++))?1:0;
1.384 +#else
1.385 + s->hit=(*(p++))?1:0;
1.386 +#endif
1.387 + s->s2->tmp.cert_type= *(p++);
1.388 + n2s(p,i);
1.389 + if (i < s->version) s->version=i;
1.390 + n2s(p,i); s->s2->tmp.cert_length=i;
1.391 + n2s(p,i); s->s2->tmp.csl=i;
1.392 + n2s(p,i); s->s2->tmp.conn_id_length=i;
1.393 + s->state=SSL2_ST_GET_SERVER_HELLO_B;
1.394 + }
1.395 +
1.396 + /* SSL2_ST_GET_SERVER_HELLO_B */
1.397 + len = 11 + (unsigned long)s->s2->tmp.cert_length + (unsigned long)s->s2->tmp.csl + (unsigned long)s->s2->tmp.conn_id_length;
1.398 + if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
1.399 + {
1.400 + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_MESSAGE_TOO_LONG);
1.401 + return -1;
1.402 + }
1.403 + j = (int)len - s->init_num;
1.404 + i = ssl2_read(s,(char *)&(buf[s->init_num]),j);
1.405 + if (i != j) return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
1.406 + if (s->msg_callback)
1.407 + s->msg_callback(0, s->version, 0, buf, (size_t)len, s, s->msg_callback_arg); /* SERVER-HELLO */
1.408 +
1.409 + /* things are looking good */
1.410 +
1.411 + p = buf + 11;
1.412 + if (s->hit)
1.413 + {
1.414 + if (s->s2->tmp.cert_length != 0)
1.415 + {
1.416 + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_LENGTH_NOT_ZERO);
1.417 + return(-1);
1.418 + }
1.419 + if (s->s2->tmp.cert_type != 0)
1.420 + {
1.421 + if (!(s->options &
1.422 + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG))
1.423 + {
1.424 + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO);
1.425 + return(-1);
1.426 + }
1.427 + }
1.428 + if (s->s2->tmp.csl != 0)
1.429 + {
1.430 + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CIPHER_LIST_NOT_ZERO);
1.431 + return(-1);
1.432 + }
1.433 + }
1.434 + else
1.435 + {
1.436 +#ifdef undef
1.437 + /* very bad */
1.438 + memset(s->session->session_id,0,
1.439 + SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES);
1.440 + s->session->session_id_length=0;
1.441 + */
1.442 +#endif
1.443 +
1.444 + /* we need to do this in case we were trying to reuse a
1.445 + * client session but others are already reusing it.
1.446 + * If this was a new 'blank' session ID, the session-id
1.447 + * length will still be 0 */
1.448 + if (s->session->session_id_length > 0)
1.449 + {
1.450 + if (!ssl_get_new_session(s,0))
1.451 + {
1.452 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.453 + return(-1);
1.454 + }
1.455 + }
1.456 +
1.457 + if (ssl2_set_certificate(s,s->s2->tmp.cert_type,
1.458 + s->s2->tmp.cert_length,p) <= 0)
1.459 + {
1.460 + ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
1.461 + return(-1);
1.462 + }
1.463 + p+=s->s2->tmp.cert_length;
1.464 +
1.465 + if (s->s2->tmp.csl == 0)
1.466 + {
1.467 + ssl2_return_error(s,SSL2_PE_NO_CIPHER);
1.468 + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_LIST);
1.469 + return(-1);
1.470 + }
1.471 +
1.472 + /* We have just received a list of ciphers back from the
1.473 + * server. We need to get the ones that match, then select
1.474 + * the one we want the most :-). */
1.475 +
1.476 + /* load the ciphers */
1.477 + sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl,
1.478 + &s->session->ciphers);
1.479 + p+=s->s2->tmp.csl;
1.480 + if (sk == NULL)
1.481 + {
1.482 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.483 + SSLerr(SSL_F_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
1.484 + return(-1);
1.485 + }
1.486 +
1.487 + (void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);
1.488 +
1.489 + /* get the array of ciphers we will accept */
1.490 + cl=SSL_get_ciphers(s);
1.491 + (void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);
1.492 +
1.493 + /*
1.494 + * If server preference flag set, choose the first
1.495 + * (highest priority) cipher the server sends, otherwise
1.496 + * client preference has priority.
1.497 + */
1.498 + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
1.499 + {
1.500 + prio = sk;
1.501 + allow = cl;
1.502 + }
1.503 + else
1.504 + {
1.505 + prio = cl;
1.506 + allow = sk;
1.507 + }
1.508 + /* In theory we could have ciphers sent back that we
1.509 + * don't want to use but that does not matter since we
1.510 + * will check against the list we originally sent and
1.511 + * for performance reasons we should not bother to match
1.512 + * the two lists up just to check. */
1.513 + for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
1.514 + {
1.515 + if (sk_SSL_CIPHER_find(allow,
1.516 + sk_SSL_CIPHER_value(prio,i)) >= 0)
1.517 + break;
1.518 + }
1.519 +
1.520 + if (i >= sk_SSL_CIPHER_num(prio))
1.521 + {
1.522 + ssl2_return_error(s,SSL2_PE_NO_CIPHER);
1.523 + SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
1.524 + return(-1);
1.525 + }
1.526 + s->session->cipher=sk_SSL_CIPHER_value(prio,i);
1.527 +
1.528 +
1.529 + if (s->session->peer != NULL) /* can't happen*/
1.530 + {
1.531 + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
1.532 + SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
1.533 + return(-1);
1.534 + }
1.535 +
1.536 + s->session->peer = s->session->sess_cert->peer_key->x509;
1.537 + /* peer_key->x509 has been set by ssl2_set_certificate. */
1.538 + CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
1.539 + }
1.540 +
1.541 + if (s->session->sess_cert == NULL
1.542 + || s->session->peer != s->session->sess_cert->peer_key->x509)
1.543 + /* can't happen */
1.544 + {
1.545 + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
1.546 + SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
1.547 + return(-1);
1.548 + }
1.549 +
1.550 + s->s2->conn_id_length=s->s2->tmp.conn_id_length;
1.551 + if (s->s2->conn_id_length > sizeof s->s2->conn_id)
1.552 + {
1.553 + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
1.554 + SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_SSL2_CONNECTION_ID_TOO_LONG);
1.555 + return -1;
1.556 + }
1.557 + memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
1.558 + return(1);
1.559 + }
1.560 +
1.561 +static int client_hello(SSL *s)
1.562 + {
1.563 + unsigned char *buf;
1.564 + unsigned char *p,*d;
1.565 +/* CIPHER **cipher;*/
1.566 + int i,n,j;
1.567 +
1.568 + buf=(unsigned char *)s->init_buf->data;
1.569 + if (s->state == SSL2_ST_SEND_CLIENT_HELLO_A)
1.570 + {
1.571 + if ((s->session == NULL) ||
1.572 + (s->session->ssl_version != s->version))
1.573 + {
1.574 + if (!ssl_get_new_session(s,0))
1.575 + {
1.576 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.577 + return(-1);
1.578 + }
1.579 + }
1.580 + /* else use the pre-loaded session */
1.581 +
1.582 + p=buf; /* header */
1.583 + d=p+9; /* data section */
1.584 + *(p++)=SSL2_MT_CLIENT_HELLO; /* type */
1.585 + s2n(SSL2_VERSION,p); /* version */
1.586 + n=j=0;
1.587 +
1.588 + n=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),d,0);
1.589 + d+=n;
1.590 +
1.591 + if (n == 0)
1.592 + {
1.593 + SSLerr(SSL_F_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
1.594 + return(-1);
1.595 + }
1.596 +
1.597 + s2n(n,p); /* cipher spec num bytes */
1.598 +
1.599 + if ((s->session->session_id_length > 0) &&
1.600 + (s->session->session_id_length <=
1.601 + SSL2_MAX_SSL_SESSION_ID_LENGTH))
1.602 + {
1.603 + i=s->session->session_id_length;
1.604 + s2n(i,p); /* session id length */
1.605 + memcpy(d,s->session->session_id,(unsigned int)i);
1.606 + d+=i;
1.607 + }
1.608 + else
1.609 + {
1.610 + s2n(0,p);
1.611 + }
1.612 +
1.613 + s->s2->challenge_length=SSL2_CHALLENGE_LENGTH;
1.614 + s2n(SSL2_CHALLENGE_LENGTH,p); /* challenge length */
1.615 + /*challenge id data*/
1.616 + if (RAND_pseudo_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH) <= 0)
1.617 + return -1;
1.618 + memcpy(d,s->s2->challenge,SSL2_CHALLENGE_LENGTH);
1.619 + d+=SSL2_CHALLENGE_LENGTH;
1.620 +
1.621 + s->state=SSL2_ST_SEND_CLIENT_HELLO_B;
1.622 + s->init_num=d-buf;
1.623 + s->init_off=0;
1.624 + }
1.625 + /* SSL2_ST_SEND_CLIENT_HELLO_B */
1.626 + return(ssl2_do_write(s));
1.627 + }
1.628 +
1.629 +static int client_master_key(SSL *s)
1.630 + {
1.631 + unsigned char *buf;
1.632 + unsigned char *p,*d;
1.633 + int clear,enc,karg,i;
1.634 + SSL_SESSION *sess;
1.635 + const EVP_CIPHER *c;
1.636 + const EVP_MD *md;
1.637 +
1.638 + buf=(unsigned char *)s->init_buf->data;
1.639 + if (s->state == SSL2_ST_SEND_CLIENT_MASTER_KEY_A)
1.640 + {
1.641 +
1.642 + if (!ssl_cipher_get_evp(s->session,&c,&md,NULL))
1.643 + {
1.644 + ssl2_return_error(s,SSL2_PE_NO_CIPHER);
1.645 + SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
1.646 + return(-1);
1.647 + }
1.648 + sess=s->session;
1.649 + p=buf;
1.650 + d=p+10;
1.651 + *(p++)=SSL2_MT_CLIENT_MASTER_KEY;/* type */
1.652 +
1.653 + i=ssl_put_cipher_by_char(s,sess->cipher,p);
1.654 + p+=i;
1.655 +
1.656 + /* make key_arg data */
1.657 + i=EVP_CIPHER_iv_length(c);
1.658 + sess->key_arg_length=i;
1.659 + if (i > SSL_MAX_KEY_ARG_LENGTH)
1.660 + {
1.661 + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
1.662 + SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
1.663 + return -1;
1.664 + }
1.665 + if (i > 0)
1.666 + if (RAND_pseudo_bytes(sess->key_arg,i) <= 0)
1.667 + return -1;
1.668 +
1.669 + /* make a master key */
1.670 + i=EVP_CIPHER_key_length(c);
1.671 + sess->master_key_length=i;
1.672 + if (i > 0)
1.673 + {
1.674 + if (i > (int)sizeof(sess->master_key))
1.675 + {
1.676 + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
1.677 + SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
1.678 + return -1;
1.679 + }
1.680 + if (RAND_bytes(sess->master_key,i) <= 0)
1.681 + {
1.682 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.683 + return(-1);
1.684 + }
1.685 + }
1.686 +
1.687 + if (sess->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC)
1.688 + enc=8;
1.689 + else if (SSL_C_IS_EXPORT(sess->cipher))
1.690 + enc=5;
1.691 + else
1.692 + enc=i;
1.693 +
1.694 + if ((int)i < enc)
1.695 + {
1.696 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.697 + SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_CIPHER_TABLE_SRC_ERROR);
1.698 + return(-1);
1.699 + }
1.700 + clear=i-enc;
1.701 + s2n(clear,p);
1.702 + memcpy(d,sess->master_key,(unsigned int)clear);
1.703 + d+=clear;
1.704 +
1.705 + enc=ssl_rsa_public_encrypt(sess->sess_cert,enc,
1.706 + &(sess->master_key[clear]),d,
1.707 + (s->s2->ssl2_rollback)?RSA_SSLV23_PADDING:RSA_PKCS1_PADDING);
1.708 + if (enc <= 0)
1.709 + {
1.710 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.711 + SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PUBLIC_KEY_ENCRYPT_ERROR);
1.712 + return(-1);
1.713 + }
1.714 +#ifdef PKCS1_CHECK
1.715 + if (s->options & SSL_OP_PKCS1_CHECK_1) d[1]++;
1.716 + if (s->options & SSL_OP_PKCS1_CHECK_2)
1.717 + sess->master_key[clear]++;
1.718 +#endif
1.719 + s2n(enc,p);
1.720 + d+=enc;
1.721 + karg=sess->key_arg_length;
1.722 + s2n(karg,p); /* key arg size */
1.723 + if (karg > (int)sizeof(sess->key_arg))
1.724 + {
1.725 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.726 + SSLerr(SSL_F_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
1.727 + return -1;
1.728 + }
1.729 + memcpy(d,sess->key_arg,(unsigned int)karg);
1.730 + d+=karg;
1.731 +
1.732 + s->state=SSL2_ST_SEND_CLIENT_MASTER_KEY_B;
1.733 + s->init_num=d-buf;
1.734 + s->init_off=0;
1.735 + }
1.736 +
1.737 + /* SSL2_ST_SEND_CLIENT_MASTER_KEY_B */
1.738 + return(ssl2_do_write(s));
1.739 + }
1.740 +
1.741 +static int client_finished(SSL *s)
1.742 + {
1.743 + unsigned char *p;
1.744 +
1.745 + if (s->state == SSL2_ST_SEND_CLIENT_FINISHED_A)
1.746 + {
1.747 + p=(unsigned char *)s->init_buf->data;
1.748 + *(p++)=SSL2_MT_CLIENT_FINISHED;
1.749 + if (s->s2->conn_id_length > sizeof s->s2->conn_id)
1.750 + {
1.751 + SSLerr(SSL_F_CLIENT_FINISHED, ERR_R_INTERNAL_ERROR);
1.752 + return -1;
1.753 + }
1.754 + memcpy(p,s->s2->conn_id,(unsigned int)s->s2->conn_id_length);
1.755 +
1.756 + s->state=SSL2_ST_SEND_CLIENT_FINISHED_B;
1.757 + s->init_num=s->s2->conn_id_length+1;
1.758 + s->init_off=0;
1.759 + }
1.760 + return(ssl2_do_write(s));
1.761 + }
1.762 +
1.763 +/* read the data and then respond */
1.764 +static int client_certificate(SSL *s)
1.765 + {
1.766 + unsigned char *buf;
1.767 + unsigned char *p,*d;
1.768 + int i;
1.769 + unsigned int n;
1.770 + int cert_ch_len;
1.771 + unsigned char *cert_ch;
1.772 +
1.773 + buf=(unsigned char *)s->init_buf->data;
1.774 +
1.775 + /* We have a cert associated with the SSL, so attach it to
1.776 + * the session if it does not have one */
1.777 +
1.778 + if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_A)
1.779 + {
1.780 + i=ssl2_read(s,(char *)&(buf[s->init_num]),
1.781 + SSL2_MAX_CERT_CHALLENGE_LENGTH+2-s->init_num);
1.782 + if (i<(SSL2_MIN_CERT_CHALLENGE_LENGTH+2-s->init_num))
1.783 + return(ssl2_part_read(s,SSL_F_CLIENT_CERTIFICATE,i));
1.784 + s->init_num += i;
1.785 + if (s->msg_callback)
1.786 + s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* REQUEST-CERTIFICATE */
1.787 +
1.788 + /* type=buf[0]; */
1.789 + /* type eq x509 */
1.790 + if (buf[1] != SSL2_AT_MD5_WITH_RSA_ENCRYPTION)
1.791 + {
1.792 + ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);
1.793 + SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_AUTHENTICATION_TYPE);
1.794 + return(-1);
1.795 + }
1.796 +
1.797 + if ((s->cert == NULL) ||
1.798 + (s->cert->key->x509 == NULL) ||
1.799 + (s->cert->key->privatekey == NULL))
1.800 + {
1.801 + s->state=SSL2_ST_X509_GET_CLIENT_CERTIFICATE;
1.802 + }
1.803 + else
1.804 + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
1.805 + }
1.806 +
1.807 + cert_ch = buf + 2;
1.808 + cert_ch_len = s->init_num - 2;
1.809 +
1.810 + if (s->state == SSL2_ST_X509_GET_CLIENT_CERTIFICATE)
1.811 + {
1.812 + X509 *x509=NULL;
1.813 + EVP_PKEY *pkey=NULL;
1.814 +
1.815 + /* If we get an error we need to
1.816 + * ssl->rwstate=SSL_X509_LOOKUP;
1.817 + * return(error);
1.818 + * We should then be retried when things are ok and we
1.819 + * can get a cert or not */
1.820 +
1.821 + i=0;
1.822 + if (s->ctx->client_cert_cb != NULL)
1.823 + {
1.824 + i=s->ctx->client_cert_cb(s,&(x509),&(pkey));
1.825 + }
1.826 +
1.827 + if (i < 0)
1.828 + {
1.829 + s->rwstate=SSL_X509_LOOKUP;
1.830 + return(-1);
1.831 + }
1.832 + s->rwstate=SSL_NOTHING;
1.833 +
1.834 + if ((i == 1) && (pkey != NULL) && (x509 != NULL))
1.835 + {
1.836 + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
1.837 + if ( !SSL_use_certificate(s,x509) ||
1.838 + !SSL_use_PrivateKey(s,pkey))
1.839 + {
1.840 + i=0;
1.841 + }
1.842 + X509_free(x509);
1.843 + EVP_PKEY_free(pkey);
1.844 + }
1.845 + else if (i == 1)
1.846 + {
1.847 + if (x509 != NULL) X509_free(x509);
1.848 + if (pkey != NULL) EVP_PKEY_free(pkey);
1.849 + SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
1.850 + i=0;
1.851 + }
1.852 +
1.853 + if (i == 0)
1.854 + {
1.855 + /* We have no client certificate to respond with
1.856 + * so send the correct error message back */
1.857 + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_B;
1.858 + p=buf;
1.859 + *(p++)=SSL2_MT_ERROR;
1.860 + s2n(SSL2_PE_NO_CERTIFICATE,p);
1.861 + s->init_off=0;
1.862 + s->init_num=3;
1.863 + /* Write is done at the end */
1.864 + }
1.865 + }
1.866 +
1.867 + if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_B)
1.868 + {
1.869 + return(ssl2_do_write(s));
1.870 + }
1.871 +
1.872 + if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_C)
1.873 + {
1.874 + EVP_MD_CTX ctx;
1.875 +
1.876 + /* ok, now we calculate the checksum
1.877 + * do it first so we can reuse buf :-) */
1.878 + p=buf;
1.879 + EVP_MD_CTX_init(&ctx);
1.880 + EVP_SignInit_ex(&ctx,s->ctx->rsa_md5, NULL);
1.881 + EVP_SignUpdate(&ctx,s->s2->key_material,
1.882 + s->s2->key_material_length);
1.883 + EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len);
1.884 + n=i2d_X509(s->session->sess_cert->peer_key->x509,&p);
1.885 + EVP_SignUpdate(&ctx,buf,(unsigned int)n);
1.886 +
1.887 + p=buf;
1.888 + d=p+6;
1.889 + *(p++)=SSL2_MT_CLIENT_CERTIFICATE;
1.890 + *(p++)=SSL2_CT_X509_CERTIFICATE;
1.891 + n=i2d_X509(s->cert->key->x509,&d);
1.892 + s2n(n,p);
1.893 +
1.894 + if (!EVP_SignFinal(&ctx,d,&n,s->cert->key->privatekey))
1.895 + {
1.896 + /* this is not good. If things have failed it
1.897 + * means there so something wrong with the key.
1.898 + * We will continue with a 0 length signature
1.899 + */
1.900 + }
1.901 + EVP_MD_CTX_cleanup(&ctx);
1.902 + s2n(n,p);
1.903 + d+=n;
1.904 +
1.905 + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_D;
1.906 + s->init_num=d-buf;
1.907 + s->init_off=0;
1.908 + }
1.909 + /* if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_D) */
1.910 + return(ssl2_do_write(s));
1.911 + }
1.912 +
1.913 +static int get_server_verify(SSL *s)
1.914 + {
1.915 + unsigned char *p;
1.916 + int i, n, len;
1.917 +
1.918 + p=(unsigned char *)s->init_buf->data;
1.919 + if (s->state == SSL2_ST_GET_SERVER_VERIFY_A)
1.920 + {
1.921 + i=ssl2_read(s,(char *)&(p[s->init_num]),1-s->init_num);
1.922 + if (i < (1-s->init_num))
1.923 + return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i));
1.924 + s->init_num += i;
1.925 +
1.926 + s->state= SSL2_ST_GET_SERVER_VERIFY_B;
1.927 + if (*p != SSL2_MT_SERVER_VERIFY)
1.928 + {
1.929 + if (p[0] != SSL2_MT_ERROR)
1.930 + {
1.931 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.932 + SSLerr(SSL_F_GET_SERVER_VERIFY,
1.933 + SSL_R_READ_WRONG_PACKET_TYPE);
1.934 + }
1.935 + else
1.936 + {
1.937 + SSLerr(SSL_F_GET_SERVER_VERIFY,SSL_R_PEER_ERROR);
1.938 + /* try to read the error message */
1.939 + i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num);
1.940 + return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i);
1.941 + }
1.942 + return(-1);
1.943 + }
1.944 + }
1.945 +
1.946 + p=(unsigned char *)s->init_buf->data;
1.947 + len = 1 + s->s2->challenge_length;
1.948 + n = len - s->init_num;
1.949 + i = ssl2_read(s,(char *)&(p[s->init_num]),n);
1.950 + if (i < n)
1.951 + return(ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i));
1.952 + if (s->msg_callback)
1.953 + s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* SERVER-VERIFY */
1.954 + p += 1;
1.955 +
1.956 + if (memcmp(p,s->s2->challenge,s->s2->challenge_length) != 0)
1.957 + {
1.958 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.959 + SSLerr(SSL_F_GET_SERVER_VERIFY,SSL_R_CHALLENGE_IS_DIFFERENT);
1.960 + return(-1);
1.961 + }
1.962 + return(1);
1.963 + }
1.964 +
1.965 +static int get_server_finished(SSL *s)
1.966 + {
1.967 + unsigned char *buf;
1.968 + unsigned char *p;
1.969 + int i, n, len;
1.970 +
1.971 + buf=(unsigned char *)s->init_buf->data;
1.972 + p=buf;
1.973 + if (s->state == SSL2_ST_GET_SERVER_FINISHED_A)
1.974 + {
1.975 + i=ssl2_read(s,(char *)&(buf[s->init_num]),1-s->init_num);
1.976 + if (i < (1-s->init_num))
1.977 + return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i));
1.978 + s->init_num += i;
1.979 +
1.980 + if (*p == SSL2_MT_REQUEST_CERTIFICATE)
1.981 + {
1.982 + s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_A;
1.983 + return(1);
1.984 + }
1.985 + else if (*p != SSL2_MT_SERVER_FINISHED)
1.986 + {
1.987 + if (p[0] != SSL2_MT_ERROR)
1.988 + {
1.989 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.990 + SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_READ_WRONG_PACKET_TYPE);
1.991 + }
1.992 + else
1.993 + {
1.994 + SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_PEER_ERROR);
1.995 + /* try to read the error message */
1.996 + i=ssl2_read(s,(char *)&(p[s->init_num]),3-s->init_num);
1.997 + return ssl2_part_read(s,SSL_F_GET_SERVER_VERIFY,i);
1.998 + }
1.999 + return(-1);
1.1000 + }
1.1001 + s->state=SSL2_ST_GET_SERVER_FINISHED_B;
1.1002 + }
1.1003 +
1.1004 + len = 1 + SSL2_SSL_SESSION_ID_LENGTH;
1.1005 + n = len - s->init_num;
1.1006 + i = ssl2_read(s,(char *)&(buf[s->init_num]), n);
1.1007 + if (i < n) /* XXX could be shorter than SSL2_SSL_SESSION_ID_LENGTH, that's the maximum */
1.1008 + return(ssl2_part_read(s,SSL_F_GET_SERVER_FINISHED,i));
1.1009 + s->init_num += i;
1.1010 + if (s->msg_callback)
1.1011 + s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* SERVER-FINISHED */
1.1012 +
1.1013 + if (!s->hit) /* new session */
1.1014 + {
1.1015 + /* new session-id */
1.1016 + /* Make sure we were not trying to re-use an old SSL_SESSION
1.1017 + * or bad things can happen */
1.1018 + /* ZZZZZZZZZZZZZ */
1.1019 + s->session->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
1.1020 + memcpy(s->session->session_id,p+1,SSL2_SSL_SESSION_ID_LENGTH);
1.1021 + }
1.1022 + else
1.1023 + {
1.1024 + if (!(s->options & SSL_OP_MICROSOFT_SESS_ID_BUG))
1.1025 + {
1.1026 + if ((s->session->session_id_length > sizeof s->session->session_id)
1.1027 + || (0 != memcmp(buf + 1, s->session->session_id,
1.1028 + (unsigned int)s->session->session_id_length)))
1.1029 + {
1.1030 + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
1.1031 + SSLerr(SSL_F_GET_SERVER_FINISHED,SSL_R_SSL_SESSION_ID_IS_DIFFERENT);
1.1032 + return(-1);
1.1033 + }
1.1034 + }
1.1035 + }
1.1036 + s->state = SSL_ST_OK;
1.1037 + return(1);
1.1038 + }
1.1039 +
1.1040 +/* loads in the certificate from the server */
1.1041 +int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data)
1.1042 + {
1.1043 + STACK_OF(X509) *sk=NULL;
1.1044 + EVP_PKEY *pkey=NULL;
1.1045 + SESS_CERT *sc=NULL;
1.1046 + int i;
1.1047 + X509 *x509=NULL;
1.1048 + int ret=0;
1.1049 +
1.1050 + x509=d2i_X509(NULL,&data,(long)len);
1.1051 + if (x509 == NULL)
1.1052 + {
1.1053 + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_X509_LIB);
1.1054 + goto err;
1.1055 + }
1.1056 +
1.1057 + if ((sk=sk_X509_new_null()) == NULL || !sk_X509_push(sk,x509))
1.1058 + {
1.1059 + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_MALLOC_FAILURE);
1.1060 + goto err;
1.1061 + }
1.1062 +
1.1063 + i=ssl_verify_cert_chain(s,sk);
1.1064 +
1.1065 + if ((s->verify_mode != SSL_VERIFY_NONE) && (!i))
1.1066 + {
1.1067 + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
1.1068 + goto err;
1.1069 + }
1.1070 + ERR_clear_error(); /* but we keep s->verify_result */
1.1071 + s->session->verify_result = s->verify_result;
1.1072 +
1.1073 + /* server's cert for this session */
1.1074 + sc=ssl_sess_cert_new();
1.1075 + if (sc == NULL)
1.1076 + {
1.1077 + ret= -1;
1.1078 + goto err;
1.1079 + }
1.1080 + if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
1.1081 + s->session->sess_cert=sc;
1.1082 +
1.1083 + sc->peer_pkeys[SSL_PKEY_RSA_ENC].x509=x509;
1.1084 + sc->peer_key= &(sc->peer_pkeys[SSL_PKEY_RSA_ENC]);
1.1085 +
1.1086 + pkey=X509_get_pubkey(x509);
1.1087 + x509=NULL;
1.1088 + if (pkey == NULL)
1.1089 + {
1.1090 + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY);
1.1091 + goto err;
1.1092 + }
1.1093 + if (pkey->type != EVP_PKEY_RSA)
1.1094 + {
1.1095 + SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_PUBLIC_KEY_NOT_RSA);
1.1096 + goto err;
1.1097 + }
1.1098 +
1.1099 + if (!ssl_set_peer_cert_type(sc,SSL2_CT_X509_CERTIFICATE))
1.1100 + goto err;
1.1101 + ret=1;
1.1102 +err:
1.1103 + sk_X509_free(sk);
1.1104 + X509_free(x509);
1.1105 + EVP_PKEY_free(pkey);
1.1106 + return(ret);
1.1107 + }
1.1108 +
1.1109 +static int ssl_rsa_public_encrypt(SESS_CERT *sc, int len, unsigned char *from,
1.1110 + unsigned char *to, int padding)
1.1111 + {
1.1112 + EVP_PKEY *pkey=NULL;
1.1113 + int i= -1;
1.1114 +
1.1115 + if ((sc == NULL) || (sc->peer_key->x509 == NULL) ||
1.1116 + ((pkey=X509_get_pubkey(sc->peer_key->x509)) == NULL))
1.1117 + {
1.1118 + SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,SSL_R_NO_PUBLICKEY);
1.1119 + return(-1);
1.1120 + }
1.1121 + if (pkey->type != EVP_PKEY_RSA)
1.1122 + {
1.1123 + SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,SSL_R_PUBLIC_KEY_IS_NOT_RSA);
1.1124 + goto end;
1.1125 + }
1.1126 +
1.1127 + /* we have the public key */
1.1128 + i=RSA_public_encrypt(len,from,to,pkey->pkey.rsa,padding);
1.1129 + if (i < 0)
1.1130 + SSLerr(SSL_F_SSL_RSA_PUBLIC_ENCRYPT,ERR_R_RSA_LIB);
1.1131 +end:
1.1132 + EVP_PKEY_free(pkey);
1.1133 + return(i);
1.1134 + }
1.1135 +#else /* !OPENSSL_NO_SSL2 */
1.1136 +
1.1137 +# if PEDANTIC
1.1138 +static void *dummy=&dummy;
1.1139 +# endif
1.1140 +
1.1141 +#endif