Example #1
0
    void Cryptor::encrypt(const string &plaintext, const Key &key,
                          string *ciphertext) {
      ALIGN16 unsigned char *schedule = genKeySchedule(key);
      
      switch (mode) {
      case ECB:
        ecbEncrypt(plaintext, key, ciphertext, schedule);
        break;

      case CBC:
        cbcEncrypt(plaintext, key, ciphertext, schedule);        
        break;

      case CTR:
        break;        
      }

      delete[] schedule;
    }
Example #2
0
error_t tlsWriteRecord(TlsContext *context,
   size_t length, TlsContentType contentType)
{
   error_t error;
   uint_t i;
   size_t paddingLength;

   //Point to the TLS record
   TlsRecord *record = (TlsRecord *) context->txBuffer;
   //Format TLS record
   record->type = contentType;
   record->version = htons(context->version);
   record->length = htons(length);

   //Debug message
   TRACE_DEBUG("Sending TLS record...\r\n");
   TRACE_DEBUG_ARRAY("  ", record, length + sizeof(TlsRecord));

   //Protect record payload?
   if(context->changeCipherSpecSent)
   {
      //Message authentication is required?
      if(context->hashAlgo)
      {
#if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
         //Check whether SSL 3.0 is currently used
         if(context->version == SSL_VERSION_3_0)
         {
            //SSL 3.0 uses an older obsolete version of the HMAC construction
            error = sslComputeMac(context, context->writeMacKey,
               context->writeSeqNum, record, record->data, length, record->data + length);
            //Any error to report?
            if(error) return error;
         }
         else
#endif
#if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
         //Check whether TLS 1.0, TLS 1.1 or TLS 1.2 is currently used
         if(context->version >= TLS_VERSION_1_0)
         {
            //TLS uses a HMAC construction
            hmacInit(&context->hmacContext, context->hashAlgo,
               context->writeMacKey, context->macKeyLength);
            //Compute MAC over the sequence number and the record contents
            hmacUpdate(&context->hmacContext, context->writeSeqNum, sizeof(TlsSequenceNumber));
            hmacUpdate(&context->hmacContext, record, length + sizeof(TlsRecord));
            //Append the resulting MAC to the message
            hmacFinal(&context->hmacContext, record->data + length);
         }
         else
#endif
         //The negotiated TLS version is not valid...
         {
            //Report an error
            return ERROR_INVALID_VERSION;
         }

         //Debug message
         TRACE_DEBUG("Write sequence number:\r\n");
         TRACE_DEBUG_ARRAY("  ", context->writeSeqNum, sizeof(TlsSequenceNumber));
         TRACE_DEBUG("Computed MAC:\r\n");
         TRACE_DEBUG_ARRAY("  ", record->data + length, context->hashAlgo->digestSize);

         //Adjust the length of the message
         length += context->hashAlgo->digestSize;
         //Fix length field
         record->length = htons(length);

         //Increment sequence number
         tlsIncSequenceNumber(context->writeSeqNum);
      }

      //Encryption is required?
      if(context->cipherAlgo)
      {
#if (TLS_STREAM_CIPHER_SUPPORT == ENABLED)
         //Stream cipher?
         if(context->cipherMode == CIPHER_MODE_STREAM)
         {
            //Debug message
            TRACE_DEBUG("Record before encryption:\r\n");
            TRACE_DEBUG_ARRAY("  ", record, length + sizeof(TlsRecord));
            //Encrypt record contents
            context->cipherAlgo->encryptStream(context->writeCipherContext,
               record->data, record->data, length);
         }
         else
#endif
#if (TLS_CBC_CIPHER_SUPPORT == ENABLED)
         //CBC block cipher?
         if(context->cipherMode == CIPHER_MODE_CBC)
         {
#if (TLS_MAX_VERSION >= TLS_VERSION_1_1 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
            //TLS 1.1 and 1.2 use an explicit IV
            if(context->version >= TLS_VERSION_1_1)
            {
               //Make room for the IV at the beginning of the data
               memmove(record->data + context->recordIvLength, record->data, length);

               //The initialization vector should be chosen at random
               error = context->prngAlgo->read(context->prngContext,
                  record->data, context->recordIvLength);
               //Any error to report?
               if(error) return error;

               //Adjust the length of the message
               length += context->recordIvLength;
            }
#endif
            //Get the actual amount of bytes in the last block
            paddingLength = (length + 1) % context->cipherAlgo->blockSize;
            //Padding is added to force the length of the plaintext to be
            //an integral multiple of the cipher's block length
            if(paddingLength > 0)
               paddingLength = context->cipherAlgo->blockSize - paddingLength;

            //Write padding bytes
            for(i = 0; i <= paddingLength; i++)
               record->data[length + i] = paddingLength;

            //Compute the length of the resulting message
            length += paddingLength + 1;
            //Fix length field
            record->length = htons(length);

            //Debug message
            TRACE_DEBUG("Record before encryption:\r\n");
            TRACE_DEBUG_ARRAY("  ", record, length + sizeof(TlsRecord));

            //CBC encryption
            error = cbcEncrypt(context->cipherAlgo, context->writeCipherContext,
               context->writeIv, record->data, record->data, length);
            //Any error to report?
            if(error) return error;
         }
         else
#endif
#if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_GCM_CIPHER_SUPPORT == ENABLED)
         //AEAD cipher?
         if(context->cipherMode == CIPHER_MODE_CCM ||
            context->cipherMode == CIPHER_MODE_GCM)
         {
            uint8_t *data;
            uint8_t *tag;
            size_t nonceLength;
            uint8_t nonce[12];
            uint8_t a[13];

            //Determine the total length of the nonce
            nonceLength = context->fixedIvLength + context->recordIvLength;
            //The salt is the implicit part of the nonce and is not sent in the packet
            memcpy(nonce, context->writeIv, context->fixedIvLength);

            //The explicit part of the nonce is chosen by the sender
            error = context->prngAlgo->read(context->prngContext,
               nonce + context->fixedIvLength, context->recordIvLength);
            //Any error to report?
            if(error) return error;

            //Make room for the explicit nonce at the beginning of the record
            memmove(record->data + context->recordIvLength, record->data, length);
            //The explicit part of the nonce is carried in each TLS record
            memcpy(record->data, nonce + context->fixedIvLength, context->recordIvLength);

            //Additional data to be authenticated
            memcpy(a, context->writeSeqNum, sizeof(TlsSequenceNumber));
            memcpy(a + sizeof(TlsSequenceNumber), record, sizeof(TlsRecord));

            //Plaintext data
            data = record->data + context->recordIvLength;
            //Buffer where to store the authentication tag
            tag = data + length;

#if (TLS_CCM_CIPHER_SUPPORT == ENABLED)
            //CCM cipher mode?
            if(context->cipherMode == CIPHER_MODE_CCM)
            {
               //Authenticated encryption using CCM
               error = ccmEncrypt(context->cipherAlgo, context->writeCipherContext,
                  nonce, nonceLength, a, 13, data, data, length, tag, context->authTagLength);
            }
            else
#endif
#if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
            //GCM cipher mode?
            if(context->cipherMode == CIPHER_MODE_GCM)
            {
               //Authenticated encryption using GCM
               error = gcmEncrypt(context->cipherAlgo, context->writeCipherContext,
                  nonce, nonceLength, a, 13, data, data, length, tag, context->authTagLength);
            }
            else
#endif
            //Invalid cipher mode?
            {
               //The specified cipher mode is not supported
               error = ERROR_UNSUPPORTED_CIPHER_MODE;
            }

            //Failed to encrypt data?
            if(error) return error;

            //Compute the length of the resulting message
            length += context->recordIvLength + context->authTagLength;
            //Fix length field
            record->length = htons(length);

            //Increment sequence number
            tlsIncSequenceNumber(context->writeSeqNum);
         }
         else
#endif
         //Invalid cipher mode?
         {
            //The specified cipher mode is not supported
            return ERROR_UNSUPPORTED_CIPHER_MODE;
         }

         //Debug message
         TRACE_DEBUG("Encrypted record:\r\n");
         TRACE_DEBUG_ARRAY("  ", record, length + sizeof(TlsRecord));
      }
   }

   //Compute the length of the complete TLS record
   length += sizeof(TlsRecord);
   //Send TLS record
   return tlsIoWrite(context, record, length);
}