Ejemplo n.º 1
0
error_t tlsShutdown(TlsContext *context)
{
   error_t error;

   //Invalid TLS context?
   if(context == NULL)
      return ERROR_INVALID_PARAMETER;

   //Check current state
   if(context->state == TLS_STATE_APPLICATION_DATA ||
      context->state == TLS_STATE_CLOSED)
   {
      //Notifies the recipient that the sender will not send
      //any more messages on this connection
      error = tlsSendAlert(context, TLS_ALERT_LEVEL_WARNING, TLS_ALERT_CLOSE_NOTIFY);
      //Update FSM state
      context->state = TLS_STATE_CLOSED;
   }
   else
   {
      //Report an error
      error = ERROR_NOT_CONNECTED;
   }

   //Return status code
   return error;
}
Ejemplo n.º 2
0
error_t tlsSendCertificate(TlsContext *context)
{
   error_t error;
   bool_t sendCert;
   uint8_t *p;
   size_t length;
   const char_t *pemCert;
   size_t pemCertLength;
   uint8_t *derCert;
   size_t derCertSize;
   size_t derCertLength;
   TlsCertificate *message;

   //TLS operates as a client or a server?
   if(context->entity == TLS_CONNECTION_END_CLIENT)
   {
      //The client must send a Certificate message if the server requests it
      sendCert = context->clientCertRequested ? TRUE : FALSE;

#if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
      //SSL 3.0 currently selected?
      if(context->version == SSL_VERSION_3_0)
      {
         //The server requests a certificate but no suitable certificate is available?
         if(sendCert && context->cert == NULL)
         {
            //The client should send a no_certificate alert instead
            error = tlsSendAlert(context, TLS_ALERT_LEVEL_WARNING, TLS_ALERT_NO_CERTIFICATE);
            //Any error to report?
            if(error) return error;

            //Skip Certificate message...
            sendCert = FALSE;
         }
      }
#endif
   }
   else
   {
      //The server must send a Certificate message whenever the agreed-upon
      //key exchange method uses certificates for authentication
      sendCert = (context->cert != NULL) ? TRUE : FALSE;
   }

   //Check whether a Certificate message must be sent
   if(sendCert)
   {
      //Buffer where to format the message
      p = context->txBuffer + sizeof(TlsRecord);

      //Point to the Certificate message
      message = (TlsCertificate *) p;
      //Format message header
      message->msgType = TLS_TYPE_CERTIFICATE;

      //Point to the first certificate of the list
      p = message->certificateList;
      //Length of the certificate list in bytes
      length = 0;

      //Check whether a certificate is available
      if(context->cert != NULL)
      {
         //Point to the certificate chain
         pemCert = context->cert->certChain;
         //Get the total length, in bytes, of the certificate chain
         pemCertLength = context->cert->certChainLength;
      }
      else
      {
         //If no suitable certificate is available, the message
         //contains an empty certificate list
         pemCert = NULL;
         pemCertLength = 0;
      }

      //DER encoded certificate
      derCert = NULL;
      derCertSize = 0;
      derCertLength = 0;

      //Parse the certificate chain
      while(pemCertLength > 0)
      {
         //Decode PEM certificate
         error = pemReadCertificate(&pemCert, &pemCertLength,
            &derCert, &derCertSize, &derCertLength);
         //Any error to report?
         if(error) break;

         //Total length of the certificate list
         length += derCertLength + 3;

         //Prevent the buffer from overflowing
         if((length + sizeof(TlsCertificate)) > TLS_MAX_PROTOCOL_DATA_LENGTH)
            return ERROR_MESSAGE_TOO_LONG;

         //Each certificate is preceded by a 3-byte length field
         STORE24BE(derCertLength, p);
         //Copy the current certificate
         memcpy(p + 3, derCert, derCertLength);

         //Advance data pointer
         p += derCertLength + 3;
      }

      //Free previously allocated memory
      osFreeMem(derCert);

      //A 3-byte length field shall precede the certificate list
      STORE24BE(length, message->certificateListLength);
      //Consider the 3-byte length field
      length += 3;

      //Fix message header
      STORE24BE(length, message->length);
      //Length of the complete handshake message
      length += sizeof(TlsHandshake);

      //Debug message
      TRACE_INFO("Sending Certificate message (%" PRIuSIZE " bytes)...\r\n", length);
      TRACE_DEBUG_ARRAY("  ", message, length);

      //Send handshake message
      error = tlsWriteProtocolData(context, length, TLS_TYPE_HANDSHAKE);
      //Failed to send TLS record?
      if(error) return error;
   }

   //Update FSM state
   context->state = (context->entity == TLS_CONNECTION_END_CLIENT) ?
      TLS_STATE_CLIENT_KEY_EXCHANGE : TLS_STATE_SERVER_KEY_EXCHANGE;

   //Successful processing
   return NO_ERROR;
}