my_aes.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2002 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.  This program is free software; you can redistribute it and/or modify
  3.  it under the terms of the GNU General Public License as published by
  4.  the Free Software Foundation; either version 2 of the License, or
  5.  (at your option) any later version.
  6.  This program is distributed in the hope that it will be useful,
  7.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.  GNU General Public License for more details.
  10.  You should have received a copy of the GNU General Public License
  11.  along with this program; if not, write to the Free Software
  12.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Implementation of AES Encryption for MySQL
  15.   Initial version by Peter Zaitsev  June 2002
  16. */
  17. #include <my_global.h>
  18. #include <m_string.h>
  19. #include "my_aes.h"
  20. enum encrypt_dir { AES_ENCRYPT, AES_DECRYPT };
  21. #define AES_BLOCK_SIZE 16 /* Block size in bytes */
  22. #define AES_BAD_DATA  -1 /* If bad data discovered during decoding */
  23. /* The structure for key information */
  24. typedef struct {
  25.   int nr; /* Number of rounds */
  26.   uint32   rk[4*(AES_MAXNR + 1)]; /* key schedule */
  27. } KEYINSTANCE;
  28. /*
  29.   This is internal function just keeps joint code of Key generation
  30.   SYNOPSIS
  31.     my_aes_create_key()
  32.     aes_key Address of Key Instance to be created
  33.     direction Direction (are we encoding or decoding)
  34.     key Key to use for real key creation
  35.     key_length Length of the key
  36.   DESCRIPTION
  37.   RESULT
  38.     0 ok
  39.     -1 Error Note: The current impementation never returns this
  40. */
  41. static int my_aes_create_key(KEYINSTANCE *aes_key,
  42.      enum encrypt_dir direction, const char *key,
  43.      int key_length)
  44. {
  45.   uint8 rkey[AES_KEY_LENGTH/8];  /* The real key to be used for encryption */
  46.   uint8 *rkey_end=rkey+AES_KEY_LENGTH/8; /* Real key boundary */
  47.   uint8 *ptr; /* Start of the real key*/
  48.   const char *sptr; /* Start of the working key */
  49.   const char *key_end=key+key_length; /* Working key boundary*/
  50.   bzero((char*) rkey,AES_KEY_LENGTH/8);      /* Set initial key  */
  51.   for (ptr= rkey, sptr= key; sptr < key_end; ptr++,sptr++)
  52.   {
  53.     if (ptr == rkey_end)
  54.       ptr= rkey;  /*  Just loop over tmp_key until we used all key */
  55.     *ptr^= (uint8) *sptr;
  56.   }
  57. #ifdef AES_USE_KEY_BITS
  58.   /*
  59.    This block is intended to allow more weak encryption if application 
  60.    build with libmysqld needs to correspond to export regulations
  61.    It should be never used in normal distribution as does not give 
  62.    any speed improvement.
  63.    To get worse security define AES_USE_KEY_BITS to number of bits
  64.    you want key to be. It should be divisible by 8
  65.    
  66.    WARNING: Changing this value results in changing of enryption for 
  67.    all key lengths  so altering this value will result in impossibility
  68.    to decrypt data encrypted with previous value       
  69.   */
  70. #define AES_USE_KEY_BYTES (AES_USE_KEY_BITS/8)
  71.   /*
  72.    To get weaker key we use first AES_USE_KEY_BYTES bytes of created key 
  73.    and cyclically copy them until we created all required key length
  74.   */  
  75.   for (ptr= rkey+AES_USE_KEY_BYTES, sptr=rkey ; ptr < rkey_end; 
  76.        ptr++,sptr++)
  77.   {
  78.     if (sptr == rkey+AES_USE_KEY_BYTES)
  79.       sptr=rkey;
  80.     *ptr=*sptr;   
  81.   }      
  82. #endif
  83.   if (direction == AES_DECRYPT)
  84.      aes_key->nr = rijndaelKeySetupDec(aes_key->rk, rkey, AES_KEY_LENGTH);
  85.   else
  86.      aes_key->nr = rijndaelKeySetupEnc(aes_key->rk, rkey, AES_KEY_LENGTH);
  87.   return 0;
  88. }
  89. /*
  90.   Crypt buffer with AES encryption algorithm.
  91.   SYNOPSIS
  92.      my_aes_encrypt()
  93.      source Pointer to data for encryption
  94.      source_length Size of encryption data
  95.      dest Buffer to place encrypted data (must be large enough)
  96.      key Key to be used for encryption
  97.      key_length Length of the key. Will handle keys of any length
  98.   RETURN
  99.     >= 0 Size of encrypted data
  100.     < 0 Error
  101. */
  102. int my_aes_encrypt(const char* source, int source_length, char* dest,
  103.    const char* key, int key_length)
  104. {
  105.   KEYINSTANCE aes_key;
  106.   uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
  107.   int rc; /* result codes */
  108.   int num_blocks; /* number of complete blocks */
  109.   char pad_len; /* pad size for the last block */
  110.   int i;
  111.   if ((rc= my_aes_create_key(&aes_key,AES_ENCRYPT,key,key_length)))
  112.     return rc;
  113.   num_blocks = source_length/AES_BLOCK_SIZE;
  114.   for (i = num_blocks; i > 0; i--)   /* Encode complete blocks */
  115.   {
  116.     rijndaelEncrypt(aes_key.rk, aes_key.nr, (const uint8*) source,
  117.     (uint8*) dest);
  118.     source+= AES_BLOCK_SIZE;
  119.     dest+= AES_BLOCK_SIZE;
  120.   }
  121.   /* Encode the rest. We always have incomplete block */
  122.   pad_len = AES_BLOCK_SIZE - (source_length - AES_BLOCK_SIZE*num_blocks);
  123.   memcpy(block, source, 16 - pad_len);
  124.   bfill(block + AES_BLOCK_SIZE - pad_len, pad_len, pad_len);
  125.   rijndaelEncrypt(aes_key.rk, aes_key.nr, block, (uint8*) dest);
  126.   return AES_BLOCK_SIZE*(num_blocks + 1);
  127. }
  128. /*
  129.   DeCrypt buffer with AES encryption algorithm.
  130.   SYNOPSIS
  131.     my_aes_decrypt()
  132.     source Pointer to data for decryption
  133.     source_length Size of encrypted data
  134.     dest Buffer to place decrypted data (must be large enough)
  135.     key Key to be used for decryption
  136.     key_length Length of the key. Will handle keys of any length
  137.   RETURN
  138.     >= 0 Size of encrypted data
  139.     < 0 Error
  140. */
  141. int my_aes_decrypt(const char *source, int source_length, char *dest,
  142.    const char *key, int key_length)
  143. {
  144.   KEYINSTANCE aes_key;
  145.   uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
  146.   int rc; /* Result codes */
  147.   int num_blocks; /* Number of complete blocks */
  148.   uint pad_len; /* Pad size for the last block */
  149.   int i;
  150.   if ((rc=my_aes_create_key(&aes_key,AES_DECRYPT,key,key_length)))
  151.     return rc;
  152.   num_blocks = source_length/AES_BLOCK_SIZE;
  153.   if ((source_length != num_blocks*AES_BLOCK_SIZE) || num_blocks ==0 )
  154.     return AES_BAD_DATA; /* Input size has to be even and at least one block */
  155.   for (i = num_blocks-1; i > 0; i--)   /* Decode all but last blocks */
  156.   {
  157.     rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source,
  158.     (uint8*) dest);
  159.     source+= AES_BLOCK_SIZE;
  160.     dest+= AES_BLOCK_SIZE;
  161.   }
  162.   rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source, block);
  163.   /* Use last char in the block as size */
  164.   pad_len = (uint) (uchar) block[AES_BLOCK_SIZE-1];
  165.   if (pad_len > AES_BLOCK_SIZE)
  166.     return AES_BAD_DATA;
  167.   /* We could also check whole padding but we do not really need this */
  168.   memcpy(dest, block, AES_BLOCK_SIZE - pad_len);
  169.   return AES_BLOCK_SIZE*num_blocks - pad_len;
  170. }
  171. /*
  172.   Get size of buffer which will be large enough for encrypted data
  173.   SYNOPSIS
  174.     my_aes_get_size()
  175.     source_length Length of data to be encrypted
  176.  RETURN
  177.    Size of buffer required to store encrypted data
  178. */
  179. int my_aes_get_size(int source_length)
  180. {
  181.   return AES_BLOCK_SIZE*(source_length/AES_BLOCK_SIZE)+AES_BLOCK_SIZE;
  182. }