LCOV - code coverage report
Current view: top level - home/mbr/git/openssl.git/engines - e_padlock.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 24 198 12.1 %
Date: 2014-08-02 Functions: 4 15 26.7 %
Branches: 9 117 7.7 %

           Branch data     Line data    Source code
       1                 :            : /* 
       2                 :            :  * Support for VIA PadLock Advanced Cryptography Engine (ACE)
       3                 :            :  * Written by Michal Ludvig <michal@logix.cz>
       4                 :            :  *            http://www.logix.cz/michal
       5                 :            :  *
       6                 :            :  * Big thanks to Andy Polyakov for a help with optimization, 
       7                 :            :  * assembler fixes, port to MS Windows and a lot of other 
       8                 :            :  * valuable work on this engine!
       9                 :            :  */
      10                 :            : 
      11                 :            : /* ====================================================================
      12                 :            :  * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
      13                 :            :  *
      14                 :            :  * Redistribution and use in source and binary forms, with or without
      15                 :            :  * modification, are permitted provided that the following conditions
      16                 :            :  * are met:
      17                 :            :  *
      18                 :            :  * 1. Redistributions of source code must retain the above copyright
      19                 :            :  *    notice, this list of conditions and the following disclaimer.
      20                 :            :  *
      21                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      22                 :            :  *    notice, this list of conditions and the following disclaimer in
      23                 :            :  *    the documentation and/or other materials provided with the
      24                 :            :  *    distribution.
      25                 :            :  *
      26                 :            :  * 3. All advertising materials mentioning features or use of this
      27                 :            :  *    software must display the following acknowledgment:
      28                 :            :  *    "This product includes software developed by the OpenSSL Project
      29                 :            :  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
      30                 :            :  *
      31                 :            :  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
      32                 :            :  *    endorse or promote products derived from this software without
      33                 :            :  *    prior written permission. For written permission, please contact
      34                 :            :  *    licensing@OpenSSL.org.
      35                 :            :  *
      36                 :            :  * 5. Products derived from this software may not be called "OpenSSL"
      37                 :            :  *    nor may "OpenSSL" appear in their names without prior written
      38                 :            :  *    permission of the OpenSSL Project.
      39                 :            :  *
      40                 :            :  * 6. Redistributions of any form whatsoever must retain the following
      41                 :            :  *    acknowledgment:
      42                 :            :  *    "This product includes software developed by the OpenSSL Project
      43                 :            :  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
      44                 :            :  *
      45                 :            :  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
      46                 :            :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      47                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      48                 :            :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
      49                 :            :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      50                 :            :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      51                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      52                 :            :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      53                 :            :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      54                 :            :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      55                 :            :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      56                 :            :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      57                 :            :  * ====================================================================
      58                 :            :  *
      59                 :            :  * This product includes cryptographic software written by Eric Young
      60                 :            :  * (eay@cryptsoft.com).  This product includes software written by Tim
      61                 :            :  * Hudson (tjh@cryptsoft.com).
      62                 :            :  *
      63                 :            :  */
      64                 :            : 
      65                 :            : 
      66                 :            : #include <stdio.h>
      67                 :            : #include <string.h>
      68                 :            : 
      69                 :            : #include <openssl/opensslconf.h>
      70                 :            : #include <openssl/crypto.h>
      71                 :            : #include <openssl/dso.h>
      72                 :            : #include <openssl/engine.h>
      73                 :            : #include <openssl/evp.h>
      74                 :            : #ifndef OPENSSL_NO_AES
      75                 :            : #include <openssl/aes.h>
      76                 :            : #endif
      77                 :            : #include <openssl/rand.h>
      78                 :            : #include <openssl/err.h>
      79                 :            : #include <openssl/modes.h>
      80                 :            : 
      81                 :            : #ifndef OPENSSL_NO_HW
      82                 :            : #ifndef OPENSSL_NO_HW_PADLOCK
      83                 :            : 
      84                 :            : /* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */
      85                 :            : #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
      86                 :            : #  ifndef OPENSSL_NO_DYNAMIC_ENGINE
      87                 :            : #    define DYNAMIC_ENGINE
      88                 :            : #  endif
      89                 :            : #elif (OPENSSL_VERSION_NUMBER >= 0x00907000L)
      90                 :            : #  ifdef ENGINE_DYNAMIC_SUPPORT
      91                 :            : #    define DYNAMIC_ENGINE
      92                 :            : #  endif
      93                 :            : #else
      94                 :            : #  error "Only OpenSSL >= 0.9.7 is supported"
      95                 :            : #endif
      96                 :            : 
      97                 :            : /* VIA PadLock AES is available *ONLY* on some x86 CPUs.
      98                 :            :    Not only that it doesn't exist elsewhere, but it
      99                 :            :    even can't be compiled on other platforms! */
     100                 :            :  
     101                 :            : #undef COMPILE_HW_PADLOCK
     102                 :            : #if !defined(I386_ONLY) && !defined(OPENSSL_NO_ASM)
     103                 :            : # if    defined(__i386__) || defined(__i386) ||    \
     104                 :            :         defined(__x86_64__) || defined(__x86_64) || \
     105                 :            :         defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
     106                 :            :         defined(__INTEL__)
     107                 :            : #  define COMPILE_HW_PADLOCK
     108                 :            : #  ifdef OPENSSL_NO_DYNAMIC_ENGINE
     109                 :            : static ENGINE *ENGINE_padlock (void);
     110                 :            : #  endif
     111                 :            : # endif
     112                 :            : #endif
     113                 :            : 
     114                 :            : #ifdef OPENSSL_NO_DYNAMIC_ENGINE
     115                 :            : 
     116                 :        728 : void ENGINE_load_padlock (void)
     117                 :            : {
     118                 :            : /* On non-x86 CPUs it just returns. */
     119                 :            : #ifdef COMPILE_HW_PADLOCK
     120                 :        728 :         ENGINE *toadd = ENGINE_padlock ();
     121         [ +  - ]:        728 :         if (!toadd) return;
     122                 :        728 :         ENGINE_add (toadd);
     123                 :        728 :         ENGINE_free (toadd);
     124                 :        728 :         ERR_clear_error ();
     125                 :            : #endif
     126                 :            : }
     127                 :            : 
     128                 :            : #endif
     129                 :            : 
     130                 :            : #ifdef COMPILE_HW_PADLOCK
     131                 :            : 
     132                 :            : /* Function for ENGINE detection and control */
     133                 :            : static int padlock_available(void);
     134                 :            : static int padlock_init(ENGINE *e);
     135                 :            : 
     136                 :            : /* RNG Stuff */
     137                 :            : static RAND_METHOD padlock_rand;
     138                 :            : 
     139                 :            : /* Cipher Stuff */
     140                 :            : #ifndef OPENSSL_NO_AES
     141                 :            : static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
     142                 :            : #endif
     143                 :            : 
     144                 :            : /* Engine names */
     145                 :            : static const char *padlock_id = "padlock";
     146                 :            : static char padlock_name[100];
     147                 :            : 
     148                 :            : /* Available features */
     149                 :            : static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
     150                 :            : static int padlock_use_rng = 0; /* Random Number Generator */
     151                 :            : 
     152                 :            : /* ===== Engine "management" functions ===== */
     153                 :            : 
     154                 :            : /* Prepare the ENGINE structure for registration */
     155                 :            : static int
     156                 :        728 : padlock_bind_helper(ENGINE *e)
     157                 :            : {
     158                 :            :         /* Check available features */
     159                 :        728 :         padlock_available();
     160                 :            : 
     161                 :            : #if 1   /* disable RNG for now, see commentary in vicinity of RNG code */
     162                 :        728 :         padlock_use_rng=0;
     163                 :            : #endif
     164                 :            : 
     165                 :            :         /* Generate a nice engine name with available features */
     166         [ +  - ]:        728 :         BIO_snprintf(padlock_name, sizeof(padlock_name),
     167                 :            :                 "VIA PadLock (%s, %s)", 
     168                 :            :                  padlock_use_rng ? "RNG" : "no-RNG",
     169                 :        728 :                  padlock_use_ace ? "ACE" : "no-ACE");
     170                 :            : 
     171                 :            :         /* Register everything or return with an error */ 
     172   [ +  -  +  - ]:       1456 :         if (!ENGINE_set_id(e, padlock_id) ||
     173         [ +  - ]:       1456 :             !ENGINE_set_name(e, padlock_name) ||
     174                 :            : 
     175         [ -  + ]:       1456 :             !ENGINE_set_init_function(e, padlock_init) ||
     176                 :            : #ifndef OPENSSL_NO_AES
     177 [ #  # ][ -  + ]:        728 :             (padlock_use_ace && !ENGINE_set_ciphers (e, padlock_ciphers)) ||
     178                 :            : #endif
     179         [ #  # ]:          0 :             (padlock_use_rng && !ENGINE_set_RAND (e, &padlock_rand))) {
     180                 :            :                 return 0;
     181                 :            :         }
     182                 :            : 
     183                 :            :         /* Everything looks good */
     184                 :            :         return 1;
     185                 :            : }
     186                 :            : 
     187                 :            : #ifdef OPENSSL_NO_DYNAMIC_ENGINE
     188                 :            : /* Constructor */
     189                 :            : static ENGINE *
     190                 :        728 : ENGINE_padlock(void)
     191                 :            : {
     192                 :        728 :         ENGINE *eng = ENGINE_new();
     193                 :            : 
     194         [ +  - ]:        728 :         if (!eng) {
     195                 :            :                 return NULL;
     196                 :            :         }
     197                 :            : 
     198         [ -  + ]:        728 :         if (!padlock_bind_helper(eng)) {
     199                 :          0 :                 ENGINE_free(eng);
     200                 :          0 :                 return NULL;
     201                 :            :         }
     202                 :            : 
     203                 :            :         return eng;
     204                 :            : }
     205                 :            : #endif
     206                 :            : 
     207                 :            : /* Check availability of the engine */
     208                 :            : static int
     209                 :          0 : padlock_init(ENGINE *e)
     210                 :            : {
     211 [ #  # ][ #  # ]:          0 :         return (padlock_use_rng || padlock_use_ace);
     212                 :            : }
     213                 :            : 
     214                 :            : /* This stuff is needed if this ENGINE is being compiled into a self-contained
     215                 :            :  * shared-library.
     216                 :            :  */
     217                 :            : #ifdef DYNAMIC_ENGINE
     218                 :            : static int
     219                 :            : padlock_bind_fn(ENGINE *e, const char *id)
     220                 :            : {
     221                 :            :         if (id && (strcmp(id, padlock_id) != 0)) {
     222                 :            :                 return 0;
     223                 :            :         }
     224                 :            : 
     225                 :            :         if (!padlock_bind_helper(e))  {
     226                 :            :                 return 0;
     227                 :            :         }
     228                 :            : 
     229                 :            :         return 1;
     230                 :            : }
     231                 :            : 
     232                 :            : IMPLEMENT_DYNAMIC_CHECK_FN()
     233                 :            : IMPLEMENT_DYNAMIC_BIND_FN (padlock_bind_fn)
     234                 :            : #endif /* DYNAMIC_ENGINE */
     235                 :            : 
     236                 :            : /* ===== Here comes the "real" engine ===== */
     237                 :            : 
     238                 :            : #ifndef OPENSSL_NO_AES
     239                 :            : /* Some AES-related constants */
     240                 :            : #define AES_BLOCK_SIZE          16
     241                 :            : #define AES_KEY_SIZE_128        16
     242                 :            : #define AES_KEY_SIZE_192        24
     243                 :            : #define AES_KEY_SIZE_256        32
     244                 :            : 
     245                 :            : /* Here we store the status information relevant to the 
     246                 :            :    current context. */
     247                 :            : /* BIG FAT WARNING:
     248                 :            :  *      Inline assembler in PADLOCK_XCRYPT_ASM()
     249                 :            :  *      depends on the order of items in this structure.
     250                 :            :  *      Don't blindly modify, reorder, etc!
     251                 :            :  */
     252                 :            : struct padlock_cipher_data
     253                 :            : {
     254                 :            :         unsigned char iv[AES_BLOCK_SIZE];       /* Initialization vector */
     255                 :            :         union { unsigned int pad[4];
     256                 :            :                 struct {
     257                 :            :                         int rounds:4;
     258                 :            :                         int dgst:1;     /* n/a in C3 */
     259                 :            :                         int align:1;    /* n/a in C3 */
     260                 :            :                         int ciphr:1;    /* n/a in C3 */
     261                 :            :                         unsigned int keygen:1;
     262                 :            :                         int interm:1;
     263                 :            :                         unsigned int encdec:1;
     264                 :            :                         int ksize:2;
     265                 :            :                 } b;
     266                 :            :         } cword;                /* Control word */
     267                 :            :         AES_KEY ks;             /* Encryption key */
     268                 :            : };
     269                 :            : #endif
     270                 :            : 
     271                 :            : /* Interface to assembler module */
     272                 :            : unsigned int padlock_capability();
     273                 :            : void padlock_key_bswap(AES_KEY *key);
     274                 :            : void padlock_verify_context(struct padlock_cipher_data *ctx);
     275                 :            : void padlock_reload_key();
     276                 :            : void padlock_aes_block(void *out, const void *inp,
     277                 :            :                 struct padlock_cipher_data *ctx);
     278                 :            : int  padlock_ecb_encrypt(void *out, const void *inp,
     279                 :            :                 struct padlock_cipher_data *ctx, size_t len);
     280                 :            : int  padlock_cbc_encrypt(void *out, const void *inp,
     281                 :            :                 struct padlock_cipher_data *ctx, size_t len);
     282                 :            : int  padlock_cfb_encrypt(void *out, const void *inp,
     283                 :            :                 struct padlock_cipher_data *ctx, size_t len);
     284                 :            : int  padlock_ofb_encrypt(void *out, const void *inp,
     285                 :            :                 struct padlock_cipher_data *ctx, size_t len);
     286                 :            : int  padlock_ctr32_encrypt(void *out, const void *inp,
     287                 :            :                 struct padlock_cipher_data *ctx, size_t len);
     288                 :            : int  padlock_xstore(void *out,int edx);
     289                 :            : void padlock_sha1_oneshot(void *ctx,const void *inp,size_t len);
     290                 :            : void padlock_sha1(void *ctx,const void *inp,size_t len);
     291                 :            : void padlock_sha256_oneshot(void *ctx,const void *inp,size_t len);
     292                 :            : void padlock_sha256(void *ctx,const void *inp,size_t len);
     293                 :            : 
     294                 :            : /* Load supported features of the CPU to see if
     295                 :            :    the PadLock is available. */
     296                 :            : static int
     297                 :        728 : padlock_available(void)
     298                 :            : {
     299                 :        728 :         unsigned int edx = padlock_capability();
     300                 :            : 
     301                 :            :         /* Fill up some flags */
     302                 :        728 :         padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
     303                 :        728 :         padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
     304                 :            : 
     305                 :        728 :         return padlock_use_ace + padlock_use_rng;
     306                 :            : }
     307                 :            : 
     308                 :            : /* ===== AES encryption/decryption ===== */
     309                 :            : #ifndef OPENSSL_NO_AES
     310                 :            : 
     311                 :            : #if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
     312                 :            : #define NID_aes_128_cfb NID_aes_128_cfb128
     313                 :            : #endif
     314                 :            : 
     315                 :            : #if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
     316                 :            : #define NID_aes_128_ofb NID_aes_128_ofb128
     317                 :            : #endif
     318                 :            : 
     319                 :            : #if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
     320                 :            : #define NID_aes_192_cfb NID_aes_192_cfb128
     321                 :            : #endif
     322                 :            : 
     323                 :            : #if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
     324                 :            : #define NID_aes_192_ofb NID_aes_192_ofb128
     325                 :            : #endif
     326                 :            : 
     327                 :            : #if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
     328                 :            : #define NID_aes_256_cfb NID_aes_256_cfb128
     329                 :            : #endif
     330                 :            : 
     331                 :            : #if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
     332                 :            : #define NID_aes_256_ofb NID_aes_256_ofb128
     333                 :            : #endif
     334                 :            : 
     335                 :            : /* List of supported ciphers. */
     336                 :            : static int padlock_cipher_nids[] = {
     337                 :            :         NID_aes_128_ecb,
     338                 :            :         NID_aes_128_cbc,
     339                 :            :         NID_aes_128_cfb,
     340                 :            :         NID_aes_128_ofb,
     341                 :            :         NID_aes_128_ctr,
     342                 :            : 
     343                 :            :         NID_aes_192_ecb,
     344                 :            :         NID_aes_192_cbc,
     345                 :            :         NID_aes_192_cfb,
     346                 :            :         NID_aes_192_ofb,
     347                 :            :         NID_aes_192_ctr,
     348                 :            : 
     349                 :            :         NID_aes_256_ecb,
     350                 :            :         NID_aes_256_cbc,
     351                 :            :         NID_aes_256_cfb,
     352                 :            :         NID_aes_256_ofb,
     353                 :            :         NID_aes_256_ctr
     354                 :            : };
     355                 :            : static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids)/
     356                 :            :                                       sizeof(padlock_cipher_nids[0]));
     357                 :            : 
     358                 :            : /* Function prototypes ... */
     359                 :            : static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
     360                 :            :                                 const unsigned char *iv, int enc);
     361                 :            : 
     362                 :            : #define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) +         \
     363                 :            :         ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F )      )
     364                 :            : #define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
     365                 :            :         NEAREST_ALIGNED(ctx->cipher_data))
     366                 :            : 
     367                 :            : static int
     368                 :          0 : padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
     369                 :            :                    const unsigned char *in_arg, size_t nbytes)
     370                 :            : {
     371                 :          0 :         return padlock_ecb_encrypt(out_arg,in_arg,
     372                 :          0 :                         ALIGNED_CIPHER_DATA(ctx),nbytes);
     373                 :            : }
     374                 :            : static int
     375                 :          0 : padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
     376                 :            :                    const unsigned char *in_arg, size_t nbytes)
     377                 :            : {
     378                 :          0 :         struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
     379                 :            :         int ret;
     380                 :            : 
     381                 :          0 :         memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
     382         [ #  # ]:          0 :         if ((ret = padlock_cbc_encrypt(out_arg,in_arg,cdata,nbytes)))
     383                 :          0 :                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
     384                 :          0 :         return ret;
     385                 :            : }
     386                 :            : 
     387                 :            : static int
     388                 :          0 : padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
     389                 :            :                    const unsigned char *in_arg, size_t nbytes)
     390                 :            : {
     391                 :          0 :         struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
     392                 :            :         size_t chunk;
     393                 :            : 
     394         [ #  # ]:          0 :         if ((chunk = ctx->num)) { /* borrow chunk variable */
     395                 :          0 :                 unsigned char *ivp=ctx->iv;
     396                 :            : 
     397         [ #  # ]:          0 :                 if (chunk >= AES_BLOCK_SIZE)
     398                 :            :                         return 0; /* bogus value */
     399                 :            : 
     400         [ #  # ]:          0 :                 if (ctx->encrypt)
     401         [ #  # ]:          0 :                         while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
     402                 :          0 :                                 ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
     403                 :          0 :                                 chunk++, nbytes--;
     404                 :            :                         }
     405         [ #  # ]:          0 :                 else    while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
     406                 :          0 :                                 unsigned char c = *(in_arg++);
     407                 :          0 :                                 *(out_arg++) = c ^ ivp[chunk];
     408                 :          0 :                                 ivp[chunk++] = c, nbytes--;
     409                 :            :                         }
     410                 :            : 
     411                 :          0 :                 ctx->num = chunk%AES_BLOCK_SIZE;
     412                 :            :         }
     413                 :            : 
     414         [ #  # ]:          0 :         if (nbytes == 0)
     415                 :            :                 return 1;
     416                 :            : 
     417                 :          0 :         memcpy (cdata->iv, ctx->iv, AES_BLOCK_SIZE);
     418                 :            : 
     419         [ #  # ]:          0 :         if ((chunk = nbytes & ~(AES_BLOCK_SIZE-1))) {
     420         [ #  # ]:          0 :                 if (!padlock_cfb_encrypt(out_arg,in_arg,cdata,chunk))
     421                 :            :                         return 0;
     422                 :          0 :                 nbytes  -= chunk;
     423                 :            :         }
     424                 :            : 
     425         [ #  # ]:          0 :         if (nbytes) {
     426                 :          0 :                 unsigned char *ivp = cdata->iv;
     427                 :            : 
     428                 :          0 :                 out_arg += chunk;
     429                 :          0 :                 in_arg  += chunk;
     430                 :          0 :                 ctx->num = nbytes;
     431         [ #  # ]:          0 :                 if (cdata->cword.b.encdec) {
     432                 :          0 :                         cdata->cword.b.encdec=0;
     433                 :          0 :                         padlock_reload_key();
     434                 :          0 :                         padlock_aes_block(ivp,ivp,cdata);
     435                 :          0 :                         cdata->cword.b.encdec=1;
     436                 :          0 :                         padlock_reload_key();
     437         [ #  # ]:          0 :                         while(nbytes) {
     438                 :          0 :                                 unsigned char c = *(in_arg++);
     439                 :          0 :                                 *(out_arg++) = c ^ *ivp;
     440                 :          0 :                                 *(ivp++) = c, nbytes--;
     441                 :            :                         }
     442                 :            :                 }
     443                 :          0 :                 else {  padlock_reload_key();
     444                 :          0 :                         padlock_aes_block(ivp,ivp,cdata);
     445                 :          0 :                         padlock_reload_key();
     446         [ #  # ]:          0 :                         while (nbytes) {
     447                 :          0 :                                 *ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
     448                 :          0 :                                 ivp++, nbytes--;
     449                 :            :                         }
     450                 :            :                 }
     451                 :            :         }
     452                 :            : 
     453                 :          0 :         memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
     454                 :            : 
     455                 :          0 :         return 1;
     456                 :            : }
     457                 :            : 
     458                 :            : static int
     459                 :          0 : padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
     460                 :            :                    const unsigned char *in_arg, size_t nbytes)
     461                 :            : {
     462                 :          0 :         struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
     463                 :            :         size_t chunk;
     464                 :            : 
     465                 :            :         /* ctx->num is maintained in byte-oriented modes,
     466                 :            :            such as CFB and OFB... */
     467         [ #  # ]:          0 :         if ((chunk = ctx->num)) { /* borrow chunk variable */
     468                 :          0 :                 unsigned char *ivp=ctx->iv;
     469                 :            : 
     470         [ #  # ]:          0 :                 if (chunk >= AES_BLOCK_SIZE)
     471                 :            :                         return 0; /* bogus value */
     472                 :            : 
     473         [ #  # ]:          0 :                 while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
     474                 :          0 :                         *(out_arg++) = *(in_arg++) ^ ivp[chunk];
     475                 :          0 :                         chunk++, nbytes--;
     476                 :            :                 }
     477                 :            : 
     478                 :          0 :                 ctx->num = chunk%AES_BLOCK_SIZE;
     479                 :            :         }
     480                 :            : 
     481         [ #  # ]:          0 :         if (nbytes == 0)
     482                 :            :                 return 1;
     483                 :            : 
     484                 :          0 :         memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
     485                 :            : 
     486         [ #  # ]:          0 :         if ((chunk = nbytes & ~(AES_BLOCK_SIZE-1))) {
     487         [ #  # ]:          0 :                 if (!padlock_ofb_encrypt(out_arg,in_arg,cdata,chunk))
     488                 :            :                         return 0;
     489                 :          0 :                 nbytes -= chunk;
     490                 :            :         }
     491                 :            : 
     492         [ #  # ]:          0 :         if (nbytes) {
     493                 :          0 :                 unsigned char *ivp = cdata->iv;
     494                 :            : 
     495                 :          0 :                 out_arg += chunk;
     496                 :          0 :                 in_arg  += chunk;
     497                 :          0 :                 ctx->num = nbytes;
     498                 :          0 :                 padlock_reload_key();   /* empirically found */
     499                 :          0 :                 padlock_aes_block(ivp,ivp,cdata);
     500                 :          0 :                 padlock_reload_key();   /* empirically found */
     501         [ #  # ]:          0 :                 while (nbytes) {
     502                 :          0 :                         *(out_arg++) = *(in_arg++) ^ *ivp;
     503                 :          0 :                         ivp++, nbytes--;
     504                 :            :                 }
     505                 :            :         }
     506                 :            : 
     507                 :          0 :         memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
     508                 :            : 
     509                 :          0 :         return 1;
     510                 :            : }
     511                 :            : 
     512                 :          0 : static void padlock_ctr32_encrypt_glue(const unsigned char *in,
     513                 :            :                         unsigned char *out, size_t blocks,
     514                 :            :                         struct padlock_cipher_data *ctx,
     515                 :            :                         const unsigned char *ivec)
     516                 :            : {
     517                 :          0 :         memcpy(ctx->iv,ivec,AES_BLOCK_SIZE);
     518                 :          0 :         padlock_ctr32_encrypt(out,in,ctx,AES_BLOCK_SIZE*blocks);
     519                 :          0 : }
     520                 :            : 
     521                 :            : static int
     522                 :          0 : padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
     523                 :            :                    const unsigned char *in_arg, size_t nbytes)
     524                 :            : {
     525                 :          0 :         struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
     526                 :          0 :         unsigned int num = ctx->num;
     527                 :            : 
     528                 :          0 :         CRYPTO_ctr128_encrypt_ctr32(in_arg,out_arg,nbytes,
     529                 :          0 :                         cdata,ctx->iv,ctx->buf,&num,
     530                 :            :                         (ctr128_f)padlock_ctr32_encrypt_glue);
     531                 :            : 
     532                 :          0 :         ctx->num = (size_t)num;
     533                 :          0 :         return 1;
     534                 :            : }
     535                 :            : 
     536                 :            : #define EVP_CIPHER_block_size_ECB       AES_BLOCK_SIZE
     537                 :            : #define EVP_CIPHER_block_size_CBC       AES_BLOCK_SIZE
     538                 :            : #define EVP_CIPHER_block_size_OFB       1
     539                 :            : #define EVP_CIPHER_block_size_CFB       1
     540                 :            : #define EVP_CIPHER_block_size_CTR       1
     541                 :            : 
     542                 :            : /* Declaring so many ciphers by hand would be a pain.
     543                 :            :    Instead introduce a bit of preprocessor magic :-) */
     544                 :            : #define DECLARE_AES_EVP(ksize,lmode,umode)      \
     545                 :            : static const EVP_CIPHER padlock_aes_##ksize##_##lmode = {       \
     546                 :            :         NID_aes_##ksize##_##lmode,              \
     547                 :            :         EVP_CIPHER_block_size_##umode,  \
     548                 :            :         AES_KEY_SIZE_##ksize,           \
     549                 :            :         AES_BLOCK_SIZE,                 \
     550                 :            :         0 | EVP_CIPH_##umode##_MODE,    \
     551                 :            :         padlock_aes_init_key,           \
     552                 :            :         padlock_##lmode##_cipher,       \
     553                 :            :         NULL,                           \
     554                 :            :         sizeof(struct padlock_cipher_data) + 16,        \
     555                 :            :         EVP_CIPHER_set_asn1_iv,         \
     556                 :            :         EVP_CIPHER_get_asn1_iv,         \
     557                 :            :         NULL,                           \
     558                 :            :         NULL                            \
     559                 :            : }
     560                 :            : 
     561                 :            : DECLARE_AES_EVP(128,ecb,ECB);
     562                 :            : DECLARE_AES_EVP(128,cbc,CBC);
     563                 :            : DECLARE_AES_EVP(128,cfb,CFB);
     564                 :            : DECLARE_AES_EVP(128,ofb,OFB);
     565                 :            : DECLARE_AES_EVP(128,ctr,CTR);
     566                 :            : 
     567                 :            : DECLARE_AES_EVP(192,ecb,ECB);
     568                 :            : DECLARE_AES_EVP(192,cbc,CBC);
     569                 :            : DECLARE_AES_EVP(192,cfb,CFB);
     570                 :            : DECLARE_AES_EVP(192,ofb,OFB);
     571                 :            : DECLARE_AES_EVP(192,ctr,CTR);
     572                 :            : 
     573                 :            : DECLARE_AES_EVP(256,ecb,ECB);
     574                 :            : DECLARE_AES_EVP(256,cbc,CBC);
     575                 :            : DECLARE_AES_EVP(256,cfb,CFB);
     576                 :            : DECLARE_AES_EVP(256,ofb,OFB);
     577                 :            : DECLARE_AES_EVP(256,ctr,CTR);
     578                 :            : 
     579                 :            : static int
     580                 :          0 : padlock_ciphers (ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid)
     581                 :            : {
     582                 :            :         /* No specific cipher => return a list of supported nids ... */
     583         [ #  # ]:          0 :         if (!cipher) {
     584                 :          0 :                 *nids = padlock_cipher_nids;
     585                 :          0 :                 return padlock_cipher_nids_num;
     586                 :            :         }
     587                 :            : 
     588                 :            :         /* ... or the requested "cipher" otherwise */
     589   [ #  #  #  #  :          0 :         switch (nid) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     590                 :            :           case NID_aes_128_ecb:
     591                 :          0 :             *cipher = &padlock_aes_128_ecb;
     592                 :          0 :             break;
     593                 :            :           case NID_aes_128_cbc:
     594                 :          0 :             *cipher = &padlock_aes_128_cbc;
     595                 :          0 :             break;
     596                 :            :           case NID_aes_128_cfb:
     597                 :          0 :             *cipher = &padlock_aes_128_cfb;
     598                 :          0 :             break;
     599                 :            :           case NID_aes_128_ofb:
     600                 :          0 :             *cipher = &padlock_aes_128_ofb;
     601                 :          0 :             break;
     602                 :            :           case NID_aes_128_ctr:
     603                 :          0 :             *cipher = &padlock_aes_128_ctr;
     604                 :          0 :             break;
     605                 :            : 
     606                 :            :           case NID_aes_192_ecb:
     607                 :          0 :             *cipher = &padlock_aes_192_ecb;
     608                 :          0 :             break;
     609                 :            :           case NID_aes_192_cbc:
     610                 :          0 :             *cipher = &padlock_aes_192_cbc;
     611                 :          0 :             break;
     612                 :            :           case NID_aes_192_cfb:
     613                 :          0 :             *cipher = &padlock_aes_192_cfb;
     614                 :          0 :             break;
     615                 :            :           case NID_aes_192_ofb:
     616                 :          0 :             *cipher = &padlock_aes_192_ofb;
     617                 :          0 :             break;
     618                 :            :           case NID_aes_192_ctr:
     619                 :          0 :             *cipher = &padlock_aes_192_ctr;
     620                 :          0 :             break;
     621                 :            : 
     622                 :            :           case NID_aes_256_ecb:
     623                 :          0 :             *cipher = &padlock_aes_256_ecb;
     624                 :          0 :             break;
     625                 :            :           case NID_aes_256_cbc:
     626                 :          0 :             *cipher = &padlock_aes_256_cbc;
     627                 :          0 :             break;
     628                 :            :           case NID_aes_256_cfb:
     629                 :          0 :             *cipher = &padlock_aes_256_cfb;
     630                 :          0 :             break;
     631                 :            :           case NID_aes_256_ofb:
     632                 :          0 :             *cipher = &padlock_aes_256_ofb;
     633                 :          0 :             break;
     634                 :            :           case NID_aes_256_ctr:
     635                 :          0 :             *cipher = &padlock_aes_256_ctr;
     636                 :          0 :             break;
     637                 :            : 
     638                 :            :           default:
     639                 :            :             /* Sorry, we don't support this NID */
     640                 :          0 :             *cipher = NULL;
     641                 :          0 :             return 0;
     642                 :            :         }
     643                 :            : 
     644                 :            :         return 1;
     645                 :            : }
     646                 :            : 
     647                 :            : /* Prepare the encryption key for PadLock usage */
     648                 :            : static int
     649                 :          0 : padlock_aes_init_key (EVP_CIPHER_CTX *ctx, const unsigned char *key,
     650                 :            :                       const unsigned char *iv, int enc)
     651                 :            : {
     652                 :            :         struct padlock_cipher_data *cdata;
     653                 :          0 :         int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8;
     654                 :          0 :         unsigned long mode = EVP_CIPHER_CTX_mode(ctx);
     655                 :            : 
     656         [ #  # ]:          0 :         if (key==NULL) return 0;        /* ERROR */
     657                 :            : 
     658                 :          0 :         cdata = ALIGNED_CIPHER_DATA(ctx);
     659                 :            :         memset(cdata, 0, sizeof(struct padlock_cipher_data));
     660                 :            : 
     661                 :            :         /* Prepare Control word. */
     662         [ #  # ]:          0 :         if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE)
     663                 :          0 :                 cdata->cword.b.encdec = 0;
     664                 :            :         else
     665                 :          0 :                 cdata->cword.b.encdec = (ctx->encrypt == 0);
     666                 :          0 :         cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
     667                 :          0 :         cdata->cword.b.ksize = (key_len - 128) / 64;
     668                 :            : 
     669      [ #  #  # ]:          0 :         switch(key_len) {
     670                 :            :                 case 128:
     671                 :            :                         /* PadLock can generate an extended key for
     672                 :            :                            AES128 in hardware */
     673                 :          0 :                         memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
     674                 :          0 :                         cdata->cword.b.keygen = 0;
     675                 :          0 :                         break;
     676                 :            : 
     677                 :            :                 case 192:
     678                 :            :                 case 256:
     679                 :            :                         /* Generate an extended AES key in software.
     680                 :            :                            Needed for AES192/AES256 */
     681                 :            :                         /* Well, the above applies to Stepping 8 CPUs
     682                 :            :                            and is listed as hardware errata. They most
     683                 :            :                            likely will fix it at some point and then
     684                 :            :                            a check for stepping would be due here. */
     685         [ #  # ]:          0 :                         if ((mode == EVP_CIPH_ECB_MODE ||
     686                 :            :                              mode == EVP_CIPH_CBC_MODE)
     687         [ #  # ]:          0 :                             && !enc)
     688                 :          0 :                                 AES_set_decrypt_key(key, key_len, &cdata->ks);
     689                 :            :                         else
     690                 :          0 :                                 AES_set_encrypt_key(key, key_len, &cdata->ks);
     691                 :            : #ifndef AES_ASM
     692                 :            :                         /* OpenSSL C functions use byte-swapped extended key. */
     693                 :            :                         padlock_key_bswap(&cdata->ks);
     694                 :            : #endif
     695                 :          0 :                         cdata->cword.b.keygen = 1;
     696                 :          0 :                         break;
     697                 :            : 
     698                 :            :                 default:
     699                 :            :                         /* ERROR */
     700                 :            :                         return 0;
     701                 :            :         }
     702                 :            : 
     703                 :            :         /*
     704                 :            :          * This is done to cover for cases when user reuses the
     705                 :            :          * context for new key. The catch is that if we don't do
     706                 :            :          * this, padlock_eas_cipher might proceed with old key...
     707                 :            :          */
     708                 :          0 :         padlock_reload_key ();
     709                 :            : 
     710                 :          0 :         return 1;
     711                 :            : }
     712                 :            : 
     713                 :            : #endif /* OPENSSL_NO_AES */
     714                 :            : 
     715                 :            : /* ===== Random Number Generator ===== */
     716                 :            : /*
     717                 :            :  * This code is not engaged. The reason is that it does not comply
     718                 :            :  * with recommendations for VIA RNG usage for secure applications
     719                 :            :  * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
     720                 :            :  * provide meaningful error control...
     721                 :            :  */
     722                 :            : /* Wrapper that provides an interface between the API and 
     723                 :            :    the raw PadLock RNG */
     724                 :            : static int
     725                 :          0 : padlock_rand_bytes(unsigned char *output, int count)
     726                 :            : {
     727                 :            :         unsigned int eax, buf;
     728                 :            : 
     729         [ #  # ]:          0 :         while (count >= 8) {
     730                 :          0 :                 eax = padlock_xstore(output, 0);
     731         [ #  # ]:          0 :                 if (!(eax&(1<<6)))    return 0; /* RNG disabled */
     732                 :            :                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
     733         [ #  # ]:          0 :                 if (eax&(0x1F<<10))   return 0;
     734         [ #  # ]:          0 :                 if ((eax&0x1F)==0)  continue; /* no data, retry... */
     735         [ #  # ]:          0 :                 if ((eax&0x1F)!=8)  return 0; /* fatal failure...  */
     736                 :          0 :                 output += 8;
     737                 :          0 :                 count  -= 8;
     738                 :            :         }
     739         [ #  # ]:          0 :         while (count > 0) {
     740                 :          0 :                 eax = padlock_xstore(&buf, 3);
     741         [ #  # ]:          0 :                 if (!(eax&(1<<6)))    return 0; /* RNG disabled */
     742                 :            :                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
     743         [ #  # ]:          0 :                 if (eax&(0x1F<<10))   return 0;
     744         [ #  # ]:          0 :                 if ((eax&0x1F)==0)  continue; /* no data, retry... */
     745         [ #  # ]:          0 :                 if ((eax&0x1F)!=1)  return 0; /* fatal failure...  */
     746                 :          0 :                 *output++ = (unsigned char)buf;
     747                 :          0 :                 count--;
     748                 :            :         }
     749                 :          0 :         *(volatile unsigned int *)&buf=0;
     750                 :            : 
     751                 :          0 :         return 1;
     752                 :            : }
     753                 :            : 
     754                 :            : /* Dummy but necessary function */
     755                 :            : static int
     756                 :          0 : padlock_rand_status(void)
     757                 :            : {
     758                 :          0 :         return 1;
     759                 :            : }
     760                 :            : 
     761                 :            : /* Prepare structure for registration */
     762                 :            : static RAND_METHOD padlock_rand = {
     763                 :            :         NULL,                   /* seed */
     764                 :            :         padlock_rand_bytes,     /* bytes */
     765                 :            :         NULL,                   /* cleanup */
     766                 :            :         NULL,                   /* add */
     767                 :            :         padlock_rand_bytes,     /* pseudorand */
     768                 :            :         padlock_rand_status,    /* rand status */
     769                 :            : };
     770                 :            : 
     771                 :            : #else  /* !COMPILE_HW_PADLOCK */
     772                 :            : #ifndef OPENSSL_NO_DYNAMIC_ENGINE
     773                 :            : OPENSSL_EXPORT
     774                 :            : int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
     775                 :            : OPENSSL_EXPORT
     776                 :            : int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; }
     777                 :            : IMPLEMENT_DYNAMIC_CHECK_FN()
     778                 :            : #endif
     779                 :            : #endif /* COMPILE_HW_PADLOCK */
     780                 :            : 
     781                 :            : #endif /* !OPENSSL_NO_HW_PADLOCK */
     782                 :            : #endif /* !OPENSSL_NO_HW */

Generated by: LCOV version 1.9