MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
handshake.cpp
1 /*
2  Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to the
15  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16  MA 02110-1301 USA.
17 */
18 
19 
20 /* The handshake source implements functions for creating and reading
21  * the various handshake messages.
22  */
23 
24 
25 
26 #include "runtime.hpp"
27 #include "handshake.hpp"
28 #include "yassl_int.hpp"
29 
30 
31 namespace yaSSL {
32 
33 
34 
35 // Build a client hello message from cipher suites and compression method
36 void buildClientHello(SSL& ssl, ClientHello& hello)
37 {
38  // store for pre master secret
39  ssl.useSecurity().use_connection().chVersion_ = hello.client_version_;
40 
41  ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
42  if (ssl.getSecurity().get_resuming()) {
43  hello.id_len_ = ID_LEN;
44  memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
45  ID_LEN);
46  }
47  else
48  hello.id_len_ = 0;
49  hello.suite_len_ = ssl.getSecurity().get_parms().suites_size_;
50  memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_,
51  hello.suite_len_);
52  hello.comp_len_ = 1;
53 
54  hello.set_length(sizeof(ProtocolVersion) +
55  RAN_LEN +
56  hello.id_len_ + sizeof(hello.id_len_) +
57  hello.suite_len_ + sizeof(hello.suite_len_) +
58  hello.comp_len_ + sizeof(hello.comp_len_));
59 }
60 
61 
62 // Build a server hello message
63 void buildServerHello(SSL& ssl, ServerHello& hello)
64 {
65  if (ssl.getSecurity().get_resuming()) {
66  memcpy(hello.random_,ssl.getSecurity().get_connection().server_random_,
67  RAN_LEN);
68  memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
69  ID_LEN);
70  }
71  else {
72  ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
73  ssl.getCrypto().get_random().Fill(hello.session_id_, ID_LEN);
74  }
75  hello.id_len_ = ID_LEN;
76  ssl.set_sessionID(hello.session_id_);
77 
78  hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0];
79  hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1];
80  hello.compression_method_ = hello.compression_method_;
81 
82  hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN +
83  sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM);
84 }
85 
86 
87 // add handshake from buffer into md5 and sha hashes, use handshake header
88 void hashHandShake(SSL& ssl, const input_buffer& input, uint sz)
89 {
90  const opaque* buffer = input.get_buffer() + input.get_current() -
91  HANDSHAKE_HEADER;
92  sz += HANDSHAKE_HEADER;
93  ssl.useHashes().use_MD5().update(buffer, sz);
94  ssl.useHashes().use_SHA().update(buffer, sz);
95 }
96 
97 
98 // locals
99 namespace {
100 
101 // Write a plaintext record to buffer
102 void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
103  const Message& msg)
104 {
105  buffer.allocate(RECORD_HEADER + rlHdr.length_);
106  buffer << rlHdr << msg;
107 }
108 
109 
110 // Write a plaintext record to buffer
111 void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
112  const HandShakeHeader& hsHdr, const HandShakeBase& shake)
113 {
114  buffer.allocate(RECORD_HEADER + rlHdr.length_);
115  buffer << rlHdr << hsHdr << shake;
116 }
117 
118 
119 // Build Record Layer header for Message without handshake header
120 void buildHeader(SSL& ssl, RecordLayerHeader& rlHeader, const Message& msg)
121 {
122  ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
123  rlHeader.type_ = msg.get_type();
124  rlHeader.version_.major_ = pv.major_;
125  rlHeader.version_.minor_ = pv.minor_;
126  rlHeader.length_ = msg.get_length();
127 }
128 
129 
130 // Build HandShake and RecordLayer Headers for handshake output
131 void buildHeaders(SSL& ssl, HandShakeHeader& hsHeader,
132  RecordLayerHeader& rlHeader, const HandShakeBase& shake)
133 {
134  int sz = shake.get_length();
135 
136  hsHeader.set_type(shake.get_type());
137  hsHeader.set_length(sz);
138 
139  ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
140  rlHeader.type_ = handshake;
141  rlHeader.version_.major_ = pv.major_;
142  rlHeader.version_.minor_ = pv.minor_;
143  rlHeader.length_ = sz + HANDSHAKE_HEADER;
144 }
145 
146 
147 // add handshake from buffer into md5 and sha hashes, exclude record header
148 void hashHandShake(SSL& ssl, const output_buffer& output, bool removeIV = false)
149 {
150  uint sz = output.get_size() - RECORD_HEADER;
151 
152  const opaque* buffer = output.get_buffer() + RECORD_HEADER;
153 
154  if (removeIV) { // TLSv1_1 IV
155  uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
156  sz -= blockSz;
157  buffer += blockSz;
158  }
159 
160  ssl.useHashes().use_MD5().update(buffer, sz);
161  ssl.useHashes().use_SHA().update(buffer, sz);
162 }
163 
164 
165 // calculate MD5 hash for finished
166 void buildMD5(SSL& ssl, Finished& fin, const opaque* sender)
167 {
168 
169  opaque md5_result[MD5_LEN];
170  opaque md5_inner[SIZEOF_SENDER + SECRET_LEN + PAD_MD5];
171  opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
172 
173  const opaque* master_secret =
174  ssl.getSecurity().get_connection().master_secret_;
175 
176  // make md5 inner
177  memcpy(md5_inner, sender, SIZEOF_SENDER);
178  memcpy(&md5_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
179  memcpy(&md5_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_MD5);
180 
181  ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
182  sizeof(md5_inner));
183 
184  // make md5 outer
185  memcpy(md5_outer, master_secret, SECRET_LEN);
186  memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
187  memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
188 
189  ssl.useHashes().use_MD5().get_digest(fin.set_md5(), md5_outer,
190  sizeof(md5_outer));
191 }
192 
193 
194 // calculate SHA hash for finished
195 void buildSHA(SSL& ssl, Finished& fin, const opaque* sender)
196 {
197 
198  opaque sha_result[SHA_LEN];
199  opaque sha_inner[SIZEOF_SENDER + SECRET_LEN + PAD_SHA];
200  opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
201 
202  const opaque* master_secret =
203  ssl.getSecurity().get_connection().master_secret_;
204 
205  // make sha inner
206  memcpy(sha_inner, sender, SIZEOF_SENDER);
207  memcpy(&sha_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
208  memcpy(&sha_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_SHA);
209 
210  ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
211  sizeof(sha_inner));
212 
213  // make sha outer
214  memcpy(sha_outer, master_secret, SECRET_LEN);
215  memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
216  memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
217 
218  ssl.useHashes().use_SHA().get_digest(fin.set_sha(), sha_outer,
219  sizeof(sha_outer));
220 }
221 
222 
223 // sanity checks on encrypted message size
224 static int sanity_check_message(SSL& ssl, uint msgSz)
225 {
226  uint minSz = 0;
227 
228  if (ssl.getSecurity().get_parms().cipher_type_ == block) {
229  uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
230  if (msgSz % blockSz)
231  return -1;
232 
233  minSz = ssl.getSecurity().get_parms().hash_size_ + 1; // pad byte too
234  if (blockSz > minSz)
235  minSz = blockSz;
236 
237  if (ssl.isTLSv1_1())
238  minSz += blockSz; // explicit IV
239  }
240  else { // stream
241  minSz = ssl.getSecurity().get_parms().hash_size_;
242  }
243 
244  if (msgSz < minSz)
245  return -1;
246 
247  return 0;
248 }
249 
250 
251 // decrypt input message in place, store size in case needed later
252 void decrypt_message(SSL& ssl, input_buffer& input, uint sz)
253 {
254  input_buffer plain(sz);
255  opaque* cipher = input.get_buffer() + input.get_current();
256 
257  if (sanity_check_message(ssl, sz) != 0) {
258  ssl.SetError(sanityCipher_error);
259  return;
260  }
261 
262  ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz);
263  memcpy(cipher, plain.get_buffer(), sz);
264  ssl.useSecurity().use_parms().encrypt_size_ = sz;
265 
266  if (ssl.isTLSv1_1()) // IV
267  input.set_current(input.get_current() +
268  ssl.getCrypto().get_cipher().get_blockSize());
269 }
270 
271 
272 // output operator for input_buffer
273 output_buffer& operator<<(output_buffer& output, const input_buffer& input)
274 {
275  output.write(input.get_buffer(), input.get_size());
276  return output;
277 }
278 
279 
280 // write headers, handshake hash, mac, pad, and encrypt
281 void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output)
282 {
283  uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
284  uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
285  uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz;
286  uint pad = 0;
287  uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
288 
289  if (ssl.getSecurity().get_parms().cipher_type_ == block) {
290  if (ssl.isTLSv1_1())
291  sz += blockSz; // IV
292  sz += 1; // pad byte
293  pad = (sz - RECORD_HEADER) % blockSz;
294  pad = blockSz - pad;
295  sz += pad;
296  }
297 
298  RecordLayerHeader rlHeader;
299  HandShakeHeader hsHeader;
300  buildHeaders(ssl, hsHeader, rlHeader, fin);
301  rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
302  // and pad, hanshake doesn't
303  input_buffer iv;
304  if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){
305  iv.allocate(blockSz);
306  ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz);
307  iv.add_size(blockSz);
308  }
309  uint ivSz = iv.get_size();
310  output.allocate(sz);
311  output << rlHeader << iv << hsHeader << fin;
312 
313  hashHandShake(ssl, output, ssl.isTLSv1_1() ? true : false);
314  opaque digest[SHA_LEN]; // max size
315  if (ssl.isTLS())
316  TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz,
317  output.get_size() - RECORD_HEADER - ivSz, handshake);
318  else
319  hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
320  output.get_size() - RECORD_HEADER, handshake);
321  output.write(digest, digestSz);
322 
323  if (ssl.getSecurity().get_parms().cipher_type_ == block)
324  for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
325  // pad value too
326  input_buffer cipher(rlHeader.length_);
327  ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
328  output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
329  output.set_current(RECORD_HEADER);
330  output.write(cipher.get_buffer(), cipher.get_capacity());
331 }
332 
333 
334 // build an encrypted data or alert message for output
335 void buildMessage(SSL& ssl, output_buffer& output, const Message& msg)
336 {
337  uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
338  uint sz = RECORD_HEADER + msg.get_length() + digestSz;
339  uint pad = 0;
340  uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
341 
342  if (ssl.getSecurity().get_parms().cipher_type_ == block) {
343  if (ssl.isTLSv1_1()) // IV
344  sz += blockSz;
345  sz += 1; // pad byte
346  pad = (sz - RECORD_HEADER) % blockSz;
347  pad = blockSz - pad;
348  sz += pad;
349  }
350 
351  RecordLayerHeader rlHeader;
352  buildHeader(ssl, rlHeader, msg);
353  rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
354  // and pad, hanshake doesn't
355  input_buffer iv;
356  if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){
357  iv.allocate(blockSz);
358  ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz);
359  iv.add_size(blockSz);
360  }
361 
362  uint ivSz = iv.get_size();
363  output.allocate(sz);
364  output << rlHeader << iv << msg;
365 
366  opaque digest[SHA_LEN]; // max size
367  if (ssl.isTLS())
368  TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz,
369  output.get_size() - RECORD_HEADER - ivSz, msg.get_type());
370  else
371  hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
372  output.get_size() - RECORD_HEADER, msg.get_type());
373  output.write(digest, digestSz);
374 
375  if (ssl.getSecurity().get_parms().cipher_type_ == block)
376  for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
377  // pad value too
378  input_buffer cipher(rlHeader.length_);
379  ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
380  output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
381  output.set_current(RECORD_HEADER);
382  output.write(cipher.get_buffer(), cipher.get_capacity());
383 }
384 
385 
386 // build alert message
387 void buildAlert(SSL& ssl, output_buffer& output, const Alert& alert)
388 {
389  if (ssl.getSecurity().get_parms().pending_ == false) // encrypted
390  buildMessage(ssl, output, alert);
391  else {
392  RecordLayerHeader rlHeader;
393  buildHeader(ssl, rlHeader, alert);
394  buildOutput(output, rlHeader, alert);
395  }
396 }
397 
398 
399 // build TLS finished message
400 void buildFinishedTLS(SSL& ssl, Finished& fin, const opaque* sender)
401 {
402  opaque handshake_hash[FINISHED_SZ];
403 
404  ssl.useHashes().use_MD5().get_digest(handshake_hash);
405  ssl.useHashes().use_SHA().get_digest(&handshake_hash[MD5_LEN]);
406 
407  const opaque* side;
408  if ( strncmp((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
409  side = tls_client;
410  else
411  side = tls_server;
412 
413  PRF(fin.set_md5(), TLS_FINISHED_SZ,
414  ssl.getSecurity().get_connection().master_secret_, SECRET_LEN,
415  side, FINISHED_LABEL_SZ,
416  handshake_hash, FINISHED_SZ);
417 
418  fin.set_length(TLS_FINISHED_SZ); // shorter length for TLS
419 }
420 
421 
422 // compute p_hash for MD5 or SHA-1 for TLSv1 PRF
423 void p_hash(output_buffer& result, const output_buffer& secret,
424  const output_buffer& seed, MACAlgorithm hash)
425 {
426  uint len = hash == md5 ? MD5_LEN : SHA_LEN;
427  uint times = result.get_capacity() / len;
428  uint lastLen = result.get_capacity() % len;
429  opaque previous[SHA_LEN]; // max size
430  opaque current[SHA_LEN]; // max size
432 
433  if (lastLen) times += 1;
434 
435  if (hash == md5)
436  hmac.reset(NEW_YS HMAC_MD5(secret.get_buffer(), secret.get_size()));
437  else
438  hmac.reset(NEW_YS HMAC_SHA(secret.get_buffer(), secret.get_size()));
439  // A0 = seed
440  hmac->get_digest(previous, seed.get_buffer(), seed.get_size());// A1
441  uint lastTime = times - 1;
442 
443  for (uint i = 0; i < times; i++) {
444  hmac->update(previous, len);
445  hmac->get_digest(current, seed.get_buffer(), seed.get_size());
446 
447  if (lastLen && (i == lastTime))
448  result.write(current, lastLen);
449  else {
450  result.write(current, len);
451  //memcpy(previous, current, len);
452  hmac->get_digest(previous, previous, len);
453  }
454  }
455 }
456 
457 
458 // calculate XOR for TLSv1 PRF
459 void get_xor(byte *digest, uint digLen, output_buffer& md5,
460  output_buffer& sha)
461 {
462  for (uint i = 0; i < digLen; i++)
463  digest[i] = md5[AUTO] ^ sha[AUTO];
464 }
465 
466 
467 // build MD5 part of certificate verify
468 void buildMD5_CertVerify(SSL& ssl, byte* digest)
469 {
470  opaque md5_result[MD5_LEN];
471  opaque md5_inner[SECRET_LEN + PAD_MD5];
472  opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
473 
474  const opaque* master_secret =
475  ssl.getSecurity().get_connection().master_secret_;
476 
477  // make md5 inner
478  memcpy(md5_inner, master_secret, SECRET_LEN);
479  memcpy(&md5_inner[SECRET_LEN], PAD1, PAD_MD5);
480 
481  ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
482  sizeof(md5_inner));
483 
484  // make md5 outer
485  memcpy(md5_outer, master_secret, SECRET_LEN);
486  memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
487  memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
488 
489  ssl.useHashes().use_MD5().get_digest(digest, md5_outer, sizeof(md5_outer));
490 }
491 
492 
493 // build SHA part of certificate verify
494 void buildSHA_CertVerify(SSL& ssl, byte* digest)
495 {
496  opaque sha_result[SHA_LEN];
497  opaque sha_inner[SECRET_LEN + PAD_SHA];
498  opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
499 
500  const opaque* master_secret =
501  ssl.getSecurity().get_connection().master_secret_;
502 
503  // make sha inner
504  memcpy(sha_inner, master_secret, SECRET_LEN);
505  memcpy(&sha_inner[SECRET_LEN], PAD1, PAD_SHA);
506 
507  ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
508  sizeof(sha_inner));
509 
510  // make sha outer
511  memcpy(sha_outer, master_secret, SECRET_LEN);
512  memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
513  memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
514 
515  ssl.useHashes().use_SHA().get_digest(digest, sha_outer, sizeof(sha_outer));
516 }
517 
518 
519 } // namespace for locals
520 
521 
522 // some clients still send sslv2 client hello
523 void ProcessOldClientHello(input_buffer& input, SSL& ssl)
524 {
525  if (input.get_remaining() < 2) {
526  ssl.SetError(bad_input);
527  return;
528  }
529  byte b0 = input[AUTO];
530  byte b1 = input[AUTO];
531 
532  uint16 sz = ((b0 & 0x7f) << 8) | b1;
533 
534  if (sz > input.get_remaining()) {
535  ssl.SetError(bad_input);
536  return;
537  }
538 
539  // hashHandShake manually
540  const opaque* buffer = input.get_buffer() + input.get_current();
541  ssl.useHashes().use_MD5().update(buffer, sz);
542  ssl.useHashes().use_SHA().update(buffer, sz);
543 
544  b1 = input[AUTO]; // does this value mean client_hello?
545 
546  ClientHello ch;
547  ch.client_version_.major_ = input[AUTO];
548  ch.client_version_.minor_ = input[AUTO];
549 
550  byte len[2];
551 
552  input.read(len, sizeof(len));
553  ato16(len, ch.suite_len_);
554 
555  input.read(len, sizeof(len));
556  uint16 sessionLen;
557  ato16(len, sessionLen);
558  ch.id_len_ = sessionLen;
559 
560  input.read(len, sizeof(len));
561  uint16 randomLen;
562  ato16(len, randomLen);
563 
564  if (ch.suite_len_ > MAX_SUITE_SZ || sessionLen > ID_LEN ||
565  randomLen > RAN_LEN) {
566  ssl.SetError(bad_input);
567  return;
568  }
569 
570  int j = 0;
571  for (uint16 i = 0; i < ch.suite_len_; i += 3) {
572  byte first = input[AUTO];
573  if (first) // sslv2 type
574  input.read(len, SUITE_LEN); // skip
575  else {
576  input.read(&ch.cipher_suites_[j], SUITE_LEN);
577  j += SUITE_LEN;
578  }
579  }
580  ch.suite_len_ = j;
581 
582  if (ch.id_len_)
583  input.read(ch.session_id_, ch.id_len_);
584 
585  if (randomLen < RAN_LEN)
586  memset(ch.random_, 0, RAN_LEN - randomLen);
587  input.read(&ch.random_[RAN_LEN - randomLen], randomLen);
588 
589 
590  ch.Process(input, ssl);
591 }
592 
593 
594 // Build a finished message, see 7.6.9
595 void buildFinished(SSL& ssl, Finished& fin, const opaque* sender)
596 {
597  // store current states, building requires get_digest which resets state
598  MD5 md5(ssl.getHashes().get_MD5());
599  SHA sha(ssl.getHashes().get_SHA());
600 
601  if (ssl.isTLS())
602  buildFinishedTLS(ssl, fin, sender);
603  else {
604  buildMD5(ssl, fin, sender);
605  buildSHA(ssl, fin, sender);
606  }
607 
608  // restore
609  ssl.useHashes().use_MD5() = md5;
610  ssl.useHashes().use_SHA() = sha;
611 }
612 
613 
614 /* compute SSLv3 HMAC into digest see
615  * buffer is of sz size and includes HandShake Header but not a Record Header
616  * verify means to check peers hmac
617 */
618 void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
619  ContentType content, bool verify)
620 {
621  Digest& mac = ssl.useCrypto().use_digest();
622  opaque inner[SHA_LEN + PAD_MD5 + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ];
623  opaque outer[SHA_LEN + PAD_MD5 + SHA_LEN];
624  opaque result[SHA_LEN]; // max possible sizes
625  uint digestSz = mac.get_digestSize(); // actual sizes
626  uint padSz = mac.get_padSize();
627  uint innerSz = digestSz + padSz + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ;
628  uint outerSz = digestSz + padSz + digestSz;
629 
630  // data
631  const opaque* mac_secret = ssl.get_macSecret(verify);
632  opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
633  opaque length[LENGTH_SZ];
634  c16toa(sz, length);
635  c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
636 
637  // make inner
638  memcpy(inner, mac_secret, digestSz);
639  memcpy(&inner[digestSz], PAD1, padSz);
640  memcpy(&inner[digestSz + padSz], seq, SEQ_SZ);
641  inner[digestSz + padSz + SEQ_SZ] = content;
642  memcpy(&inner[digestSz + padSz + SEQ_SZ + SIZEOF_ENUM], length, LENGTH_SZ);
643 
644  mac.update(inner, innerSz);
645  mac.get_digest(result, buffer, sz); // append content buffer
646 
647  // make outer
648  memcpy(outer, mac_secret, digestSz);
649  memcpy(&outer[digestSz], PAD2, padSz);
650  memcpy(&outer[digestSz + padSz], result, digestSz);
651 
652  mac.get_digest(digest, outer, outerSz);
653 }
654 
655 
656 // TLS type HAMC
657 void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
658  ContentType content, bool verify)
659 {
661  opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
662  opaque length[LENGTH_SZ];
663  opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len
664 
665  c16toa(sz, length);
666  c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
667 
668  MACAlgorithm algo = ssl.getSecurity().get_parms().mac_algorithm_;
669 
670  if (algo == sha)
671  hmac.reset(NEW_YS HMAC_SHA(ssl.get_macSecret(verify), SHA_LEN));
672  else if (algo == rmd)
673  hmac.reset(NEW_YS HMAC_RMD(ssl.get_macSecret(verify), RMD_LEN));
674  else
675  hmac.reset(NEW_YS HMAC_MD5(ssl.get_macSecret(verify), MD5_LEN));
676 
677  hmac->update(seq, SEQ_SZ); // seq_num
678  inner[0] = content; // type
679  inner[SIZEOF_ENUM] = ssl.getSecurity().get_connection().version_.major_;
680  inner[SIZEOF_ENUM + SIZEOF_ENUM] =
681  ssl.getSecurity().get_connection().version_.minor_; // version
682  memcpy(&inner[SIZEOF_ENUM + VERSION_SZ], length, LENGTH_SZ); // length
683  hmac->update(inner, sizeof(inner));
684  hmac->get_digest(digest, buffer, sz); // content
685 }
686 
687 
688 // compute TLSv1 PRF (pseudo random function using HMAC)
689 void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
690  const byte* label, uint labLen, const byte* seed, uint seedLen)
691 {
692  uint half = (secLen + 1) / 2;
693 
694  output_buffer md5_half(half);
695  output_buffer sha_half(half);
696  output_buffer labelSeed(labLen + seedLen);
697 
698  md5_half.write(secret, half);
699  sha_half.write(secret + half - secLen % 2, half);
700  labelSeed.write(label, labLen);
701  labelSeed.write(seed, seedLen);
702 
703  output_buffer md5_result(digLen);
704  output_buffer sha_result(digLen);
705 
706  p_hash(md5_result, md5_half, labelSeed, md5);
707  p_hash(sha_result, sha_half, labelSeed, sha);
708 
709  md5_result.set_current(0);
710  sha_result.set_current(0);
711  get_xor(digest, digLen, md5_result, sha_result);
712 }
713 
714 
715 // build certificate hashes
716 void build_certHashes(SSL& ssl, Hashes& hashes)
717 {
718  // store current states, building requires get_digest which resets state
719  MD5 md5(ssl.getHashes().get_MD5());
720  SHA sha(ssl.getHashes().get_SHA());
721 
722  if (ssl.isTLS()) {
723  ssl.useHashes().use_MD5().get_digest(hashes.md5_);
724  ssl.useHashes().use_SHA().get_digest(hashes.sha_);
725  }
726  else {
727  buildMD5_CertVerify(ssl, hashes.md5_);
728  buildSHA_CertVerify(ssl, hashes.sha_);
729  }
730 
731  // restore
732  ssl.useHashes().use_MD5() = md5;
733  ssl.useHashes().use_SHA() = sha;
734 }
735 
736 
737 
738 // do process input requests, return 0 is done, 1 is call again to complete
739 int DoProcessReply(SSL& ssl)
740 {
741  uint ready = ssl.getSocket().get_ready();
742  if (!ready)
743  ready= 64;
744 
745  // add buffered data if its there
746  input_buffer* buffered = ssl.useBuffers().TakeRawInput();
747  uint buffSz = buffered ? buffered->get_size() : 0;
748  input_buffer buffer(buffSz + ready);
749  if (buffSz) {
750  buffer.assign(buffered->get_buffer(), buffSz);
751  ysDelete(buffered);
752  buffered = 0;
753  }
754 
755  // add new data
756  uint read = ssl.useSocket().receive(buffer.get_buffer() + buffSz, ready);
757  if (read == static_cast<uint>(-1)) {
758  ssl.SetError(receive_error);
759  return 0;
760  }
761  buffer.add_size(read);
762  uint offset = 0;
763  const MessageFactory& mf = ssl.getFactory().getMessage();
764 
765  // old style sslv2 client hello?
766  if (ssl.getSecurity().get_parms().entity_ == server_end &&
767  ssl.getStates().getServer() == clientNull)
768  if (buffer.peek() != handshake) {
769  ProcessOldClientHello(buffer, ssl);
770  if (ssl.GetError())
771  return 0;
772  }
773 
774  while(!buffer.eof()) {
775  // each record
776  RecordLayerHeader hdr;
777  bool needHdr = false;
778 
779  if (static_cast<uint>(RECORD_HEADER) > buffer.get_remaining())
780  needHdr = true;
781  else {
782  buffer >> hdr;
783  ssl.verifyState(hdr);
784  }
785 
786  // make sure we have enough input in buffer to process this record
787  if (needHdr || hdr.length_ > buffer.get_remaining()) {
788  // put header in front for next time processing
789  uint extra = needHdr ? 0 : RECORD_HEADER;
790  uint sz = buffer.get_remaining() + extra;
791  ssl.useBuffers().SetRawInput(NEW_YS input_buffer(sz,
792  buffer.get_buffer() + buffer.get_current() - extra, sz));
793  return 1;
794  }
795 
796  while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) {
797  // each message in record, can be more than 1 if not encrypted
798  if (ssl.getSecurity().get_parms().pending_ == false) { // cipher on
799  // sanity check for malicious/corrupted/illegal input
800  if (buffer.get_remaining() < hdr.length_) {
801  ssl.SetError(bad_input);
802  return 0;
803  }
804  decrypt_message(ssl, buffer, hdr.length_);
805  if (ssl.GetError())
806  return 0;
807  }
808 
809  mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_));
810  if (!msg.get()) {
811  ssl.SetError(factory_error);
812  return 0;
813  }
814  buffer >> *msg;
815  msg->Process(buffer, ssl);
816  if (ssl.GetError())
817  return 0;
818  }
819  offset += hdr.length_ + RECORD_HEADER;
820  }
821  return 0;
822 }
823 
824 
825 // process input requests
826 void processReply(SSL& ssl)
827 {
828  if (ssl.GetError()) return;
829 
830  if (DoProcessReply(ssl)) {
831  // didn't complete process
832  if (!ssl.getSocket().IsNonBlocking()) {
833  // keep trying now, blocking ok
834  while (!ssl.GetError())
835  if (DoProcessReply(ssl) == 0) break;
836  }
837  else
838  // user will have try again later, non blocking
839  ssl.SetError(YasslError(SSL_ERROR_WANT_READ));
840  }
841 }
842 
843 
844 // send client_hello, no buffering
845 void sendClientHello(SSL& ssl)
846 {
847  ssl.verifyState(serverNull);
848  if (ssl.GetError()) return;
849 
850  ClientHello ch(ssl.getSecurity().get_connection().version_,
851  ssl.getSecurity().get_connection().compression_);
852  RecordLayerHeader rlHeader;
853  HandShakeHeader hsHeader;
854  output_buffer out;
855 
856  buildClientHello(ssl, ch);
857  ssl.set_random(ch.get_random(), client_end);
858  buildHeaders(ssl, hsHeader, rlHeader, ch);
859  buildOutput(out, rlHeader, hsHeader, ch);
860  hashHandShake(ssl, out);
861 
862  ssl.Send(out.get_buffer(), out.get_size());
863 }
864 
865 
866 // send client key exchange
867 void sendClientKeyExchange(SSL& ssl, BufferOutput buffer)
868 {
869  ssl.verifyState(serverHelloDoneComplete);
870  if (ssl.GetError()) return;
871 
872  ClientKeyExchange ck(ssl);
873  ck.build(ssl);
874  ssl.makeMasterSecret();
875 
876  RecordLayerHeader rlHeader;
877  HandShakeHeader hsHeader;
878  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
879  buildHeaders(ssl, hsHeader, rlHeader, ck);
880  buildOutput(*out.get(), rlHeader, hsHeader, ck);
881  hashHandShake(ssl, *out.get());
882 
883  if (buffer == buffered)
884  ssl.addBuffer(out.release());
885  else
886  ssl.Send(out->get_buffer(), out->get_size());
887 }
888 
889 
890 // send server key exchange
891 void sendServerKeyExchange(SSL& ssl, BufferOutput buffer)
892 {
893  if (ssl.GetError()) return;
894  ServerKeyExchange sk(ssl);
895  sk.build(ssl);
896  if (ssl.GetError()) return;
897 
898  RecordLayerHeader rlHeader;
899  HandShakeHeader hsHeader;
900  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
901  buildHeaders(ssl, hsHeader, rlHeader, sk);
902  buildOutput(*out.get(), rlHeader, hsHeader, sk);
903  hashHandShake(ssl, *out.get());
904 
905  if (buffer == buffered)
906  ssl.addBuffer(out.release());
907  else
908  ssl.Send(out->get_buffer(), out->get_size());
909 }
910 
911 
912 // send change cipher
913 void sendChangeCipher(SSL& ssl, BufferOutput buffer)
914 {
915  if (ssl.getSecurity().get_parms().entity_ == server_end) {
916  if (ssl.getSecurity().get_resuming())
917  ssl.verifyState(clientKeyExchangeComplete);
918  else
919  ssl.verifyState(clientFinishedComplete);
920  }
921  if (ssl.GetError()) return;
922 
923  ChangeCipherSpec ccs;
924  RecordLayerHeader rlHeader;
925  buildHeader(ssl, rlHeader, ccs);
926  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
927  buildOutput(*out.get(), rlHeader, ccs);
928 
929  if (buffer == buffered)
930  ssl.addBuffer(out.release());
931  else
932  ssl.Send(out->get_buffer(), out->get_size());
933 }
934 
935 
936 // send finished
937 void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
938 {
939  if (ssl.GetError()) return;
940 
941  Finished fin;
942  buildFinished(ssl, fin, side == client_end ? client : server);
943  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
944  cipherFinished(ssl, fin, *out.get()); // hashes handshake
945 
946  if (ssl.getSecurity().get_resuming()) {
947  if (side == server_end)
948  buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
949  }
950  else {
951  if (!ssl.getSecurity().GetContext()->GetSessionCacheOff())
952  GetSessions().add(ssl); // store session
953  if (side == client_end)
954  buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
955  }
956  ssl.useSecurity().use_connection().CleanMaster();
957 
958  if (buffer == buffered)
959  ssl.addBuffer(out.release());
960  else
961  ssl.Send(out->get_buffer(), out->get_size());
962 }
963 
964 
965 // send data
966 int sendData(SSL& ssl, const void* buffer, int sz)
967 {
968  int sent = 0;
969 
970  if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
971  ssl.SetError(no_error);
972 
973  if (ssl.GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
974  ssl.SetError(no_error);
975  ssl.SendWriteBuffered();
976  if (!ssl.GetError()) {
977  // advance sent to prvevious sent + plain size just sent
978  sent = ssl.useBuffers().prevSent + ssl.useBuffers().plainSz;
979  }
980  }
981 
982  ssl.verfiyHandShakeComplete();
983  if (ssl.GetError()) return -1;
984 
985  for (;;) {
986  int len = min(sz - sent, MAX_RECORD_SIZE);
987  output_buffer out;
988  input_buffer tmp;
989 
990  Data data;
991 
992  if (sent == sz) break;
993 
994  if (ssl.CompressionOn()) {
995  if (Compress(static_cast<const opaque*>(buffer) + sent, len,
996  tmp) == -1) {
997  ssl.SetError(compress_error);
998  return -1;
999  }
1000  data.SetData(tmp.get_size(), tmp.get_buffer());
1001  }
1002  else
1003  data.SetData(len, static_cast<const opaque*>(buffer) + sent);
1004 
1005  buildMessage(ssl, out, data);
1006  ssl.Send(out.get_buffer(), out.get_size());
1007 
1008  if (ssl.GetError()) {
1009  if (ssl.GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
1010  ssl.useBuffers().plainSz = len;
1011  ssl.useBuffers().prevSent = sent;
1012  }
1013  return -1;
1014  }
1015  sent += len;
1016  }
1017  ssl.useLog().ShowData(sent, true);
1018  return sent;
1019 }
1020 
1021 
1022 // send alert
1023 int sendAlert(SSL& ssl, const Alert& alert)
1024 {
1025  output_buffer out;
1026  buildAlert(ssl, out, alert);
1027  ssl.Send(out.get_buffer(), out.get_size());
1028 
1029  return alert.get_length();
1030 }
1031 
1032 
1033 // process input data
1034 int receiveData(SSL& ssl, Data& data, bool peek)
1035 {
1036  if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
1037  ssl.SetError(no_error);
1038 
1039  ssl.verfiyHandShakeComplete();
1040  if (ssl.GetError()) return -1;
1041 
1042  if (!ssl.HasData())
1043  processReply(ssl);
1044 
1045  if (peek)
1046  ssl.PeekData(data);
1047  else
1048  ssl.fillData(data);
1049 
1050  ssl.useLog().ShowData(data.get_length());
1051  if (ssl.GetError()) return -1;
1052 
1053  if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) {
1054  ssl.SetError(YasslError(SSL_ERROR_WANT_READ));
1055  return SSL_WOULD_BLOCK;
1056  }
1057  return data.get_length();
1058 }
1059 
1060 
1061 // send server hello
1062 void sendServerHello(SSL& ssl, BufferOutput buffer)
1063 {
1064  if (ssl.getSecurity().get_resuming())
1065  ssl.verifyState(clientKeyExchangeComplete);
1066  else
1067  ssl.verifyState(clientHelloComplete);
1068  if (ssl.GetError()) return;
1069 
1070  ServerHello sh(ssl.getSecurity().get_connection().version_,
1071  ssl.getSecurity().get_connection().compression_);
1072  RecordLayerHeader rlHeader;
1073  HandShakeHeader hsHeader;
1074  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
1075 
1076  buildServerHello(ssl, sh);
1077  ssl.set_random(sh.get_random(), server_end);
1078  buildHeaders(ssl, hsHeader, rlHeader, sh);
1079  buildOutput(*out.get(), rlHeader, hsHeader, sh);
1080  hashHandShake(ssl, *out.get());
1081 
1082  if (buffer == buffered)
1083  ssl.addBuffer(out.release());
1084  else
1085  ssl.Send(out->get_buffer(), out->get_size());
1086 }
1087 
1088 
1089 // send server hello done
1090 void sendServerHelloDone(SSL& ssl, BufferOutput buffer)
1091 {
1092  if (ssl.GetError()) return;
1093 
1094  ServerHelloDone shd;
1095  RecordLayerHeader rlHeader;
1096  HandShakeHeader hsHeader;
1097  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
1098 
1099  buildHeaders(ssl, hsHeader, rlHeader, shd);
1100  buildOutput(*out.get(), rlHeader, hsHeader, shd);
1101  hashHandShake(ssl, *out.get());
1102 
1103  if (buffer == buffered)
1104  ssl.addBuffer(out.release());
1105  else
1106  ssl.Send(out->get_buffer(), out->get_size());
1107 }
1108 
1109 
1110 // send certificate
1111 void sendCertificate(SSL& ssl, BufferOutput buffer)
1112 {
1113  if (ssl.GetError()) return;
1114 
1115  Certificate cert(ssl.getCrypto().get_certManager().get_cert());
1116  RecordLayerHeader rlHeader;
1117  HandShakeHeader hsHeader;
1118  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
1119 
1120  buildHeaders(ssl, hsHeader, rlHeader, cert);
1121  buildOutput(*out.get(), rlHeader, hsHeader, cert);
1122  hashHandShake(ssl, *out.get());
1123 
1124  if (buffer == buffered)
1125  ssl.addBuffer(out.release());
1126  else
1127  ssl.Send(out->get_buffer(), out->get_size());
1128 }
1129 
1130 
1131 // send certificate request
1132 void sendCertificateRequest(SSL& ssl, BufferOutput buffer)
1133 {
1134  if (ssl.GetError()) return;
1135 
1136  CertificateRequest request;
1137  request.Build();
1138  RecordLayerHeader rlHeader;
1139  HandShakeHeader hsHeader;
1140  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
1141 
1142  buildHeaders(ssl, hsHeader, rlHeader, request);
1143  buildOutput(*out.get(), rlHeader, hsHeader, request);
1144  hashHandShake(ssl, *out.get());
1145 
1146  if (buffer == buffered)
1147  ssl.addBuffer(out.release());
1148  else
1149  ssl.Send(out->get_buffer(), out->get_size());
1150 }
1151 
1152 
1153 // send certificate verify
1154 void sendCertificateVerify(SSL& ssl, BufferOutput buffer)
1155 {
1156  if (ssl.GetError()) return;
1157 
1158  CertificateVerify verify;
1159  verify.Build(ssl);
1160  RecordLayerHeader rlHeader;
1161  HandShakeHeader hsHeader;
1162  mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
1163 
1164  buildHeaders(ssl, hsHeader, rlHeader, verify);
1165  buildOutput(*out.get(), rlHeader, hsHeader, verify);
1166  hashHandShake(ssl, *out.get());
1167 
1168  if (buffer == buffered)
1169  ssl.addBuffer(out.release());
1170  else
1171  ssl.Send(out->get_buffer(), out->get_size());
1172 }
1173 
1174 
1175 } // namespace