AES for SPARC T4: add XTS, reorder subroutines to improve TLB locality.
[openssl.git] / crypto / evp / e_rc2.c
index 4c3bf1e64993af41e5995bd35f4f41b99e0df98d..d4c33b58d4d5374d6b28577591e0104b60216e4c 100644 (file)
  * [including the GNU Public Licence.]
  */
 
-#ifndef NO_RC2
-
 #include <stdio.h>
 #include "cryptlib.h"
+
+#ifndef OPENSSL_NO_RC2
+
 #include <openssl/evp.h>
 #include <openssl/objects.h>
 #include "evp_locl.h"
+#include <openssl/rc2.h>
 
-static int rc2_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
-       unsigned char *iv,int enc);
-static int rc2_meth_to_magic(const EVP_CIPHER *e);
-static EVP_CIPHER *rc2_magic_to_meth(int i);
+static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+                       const unsigned char *iv,int enc);
+static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx);
+static int rc2_magic_to_meth(int i);
 static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
 static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
+
+typedef struct
+       {
+       int key_bits;   /* effective key bits */
+       RC2_KEY ks;     /* key schedule */
+       } EVP_RC2_KEY;
 
-IMPLEMENT_BLOCK_CIPHER(rc2, rc2.ks, RC2, rc2, NID_rc2,
+#define data(ctx)      ((EVP_RC2_KEY *)(ctx)->cipher_data)
+
+IMPLEMENT_BLOCK_CIPHER(rc2, ks, RC2, EVP_RC2_KEY, NID_rc2,
                        8,
-                       EVP_RC2_KEY_SIZE, 8,
-                       EVP_CIPH_VARIABLE_LENGTH, rc2_init_key, NULL,
-                       rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, NULL)
+                       RC2_KEY_LENGTH, 8, 64,
+                       EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
+                       rc2_init_key, NULL,
+                       rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, 
+                       rc2_ctrl)
 
 #define RC2_40_MAGIC   0xa0
 #define RC2_64_MAGIC   0x78
 #define RC2_128_MAGIC  0x3a
 
-static EVP_CIPHER r2_64_cbc_cipher=
+static const EVP_CIPHER r2_64_cbc_cipher=
        {
        NID_rc2_64_cbc,
        8,8 /* 64 bit */,8,
-       EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH,
+       EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
        rc2_init_key,
        rc2_cbc_cipher,
        NULL,
-       sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+
-               sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)),
+       sizeof(EVP_RC2_KEY),
        rc2_set_asn1_type_and_iv,
        rc2_get_asn1_type_and_iv,
-       NULL,
+       rc2_ctrl,
        NULL
        };
 
-static EVP_CIPHER r2_40_cbc_cipher=
+static const EVP_CIPHER r2_40_cbc_cipher=
        {
        NID_rc2_40_cbc,
        8,5 /* 40 bit */,8,
-       EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH,
+       EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
        rc2_init_key,
        rc2_cbc_cipher,
        NULL,
-       sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+
-               sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)),
+       sizeof(EVP_RC2_KEY),
        rc2_set_asn1_type_and_iv,
        rc2_get_asn1_type_and_iv,
-       NULL,
+       rc2_ctrl,
        NULL
        };
 
-EVP_CIPHER *EVP_rc2_64_cbc(void)
+const EVP_CIPHER *EVP_rc2_64_cbc(void)
        {
        return(&r2_64_cbc_cipher);
        }
 
-EVP_CIPHER *EVP_rc2_40_cbc(void)
+const EVP_CIPHER *EVP_rc2_40_cbc(void)
        {
        return(&r2_40_cbc_cipher);
        }
        
-static int rc2_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
-            unsigned char *iv, int enc)
+static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+                       const unsigned char *iv, int enc)
        {
-       RC2_set_key(&(ctx->c.rc2.ks),EVP_CIPHER_CTX_key_length(ctx),
-                       key,EVP_CIPHER_key_length(ctx->cipher)*8);
+       RC2_set_key(&data(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx),
+                   key,data(ctx)->key_bits);
        return 1;
        }
 
-static int rc2_meth_to_magic(const EVP_CIPHER *e)
+static int rc2_meth_to_magic(EVP_CIPHER_CTX *e)
        {
        int i;
 
-       i=EVP_CIPHER_key_length(e);
-       if      (i == 16) return(RC2_128_MAGIC);
-       else if (i == 8)  return(RC2_64_MAGIC);
-       else if (i == 5)  return(RC2_40_MAGIC);
+       EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i);
+       if      (i == 128) return(RC2_128_MAGIC);
+       else if (i == 64)  return(RC2_64_MAGIC);
+       else if (i == 40)  return(RC2_40_MAGIC);
        else return(0);
        }
 
-static EVP_CIPHER *rc2_magic_to_meth(int i)
+static int rc2_magic_to_meth(int i)
        {
-       if      (i == RC2_128_MAGIC) return(EVP_rc2_cbc());
-       else if (i == RC2_64_MAGIC)  return(EVP_rc2_64_cbc());
-       else if (i == RC2_40_MAGIC)  return(EVP_rc2_40_cbc());
+       if      (i == RC2_128_MAGIC) return 128;
+       else if (i == RC2_64_MAGIC)  return 64;
+       else if (i == RC2_40_MAGIC)  return 40;
        else
                {
                EVPerr(EVP_F_RC2_MAGIC_TO_METH,EVP_R_UNSUPPORTED_KEY_SIZE);
-               return(NULL);
+               return(0);
                }
        }
 
 static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
        {
        long num=0;
-       int i=0,l;
-       EVP_CIPHER *e;
+       int i=0;
+       int key_bits;
+       unsigned int l;
+       unsigned char iv[EVP_MAX_IV_LENGTH];
 
        if (type != NULL)
                {
                l=EVP_CIPHER_CTX_iv_length(c);
-               i=ASN1_TYPE_get_int_octetstring(type,&num,c->oiv,l);
-               if (i != l)
+               OPENSSL_assert(l <= sizeof(iv));
+               i=ASN1_TYPE_get_int_octetstring(type,&num,iv,l);
+               if (i != (int)l)
                        return(-1);
-               else if (i > 0)
-                       memcpy(c->iv,c->oiv,l);
-               e=rc2_magic_to_meth((int)num);
-               if (e == NULL)
+               key_bits =rc2_magic_to_meth((int)num);
+               if (!key_bits)
                        return(-1);
-               if (e != EVP_CIPHER_CTX_cipher(c))
-                       {
-                       EVP_CIPHER_CTX_cipher(c)=e;
-                       EVP_CIPHER_CTX_set_key_length(c, EVP_CIPHER_key_length(c));
-                       rc2_init_key(c,NULL,NULL,1);
-                       }
+               if(i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1))
+                       return -1;
+               EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL);
+               EVP_CIPHER_CTX_set_key_length(c, key_bits / 8);
                }
        return(i);
        }
@@ -188,11 +198,41 @@ static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 
        if (type != NULL)
                {
-               num=rc2_meth_to_magic(EVP_CIPHER_CTX_cipher(c));
+               num=rc2_meth_to_magic(c);
                j=EVP_CIPHER_CTX_iv_length(c);
                i=ASN1_TYPE_set_int_octetstring(type,num,c->oiv,j);
                }
        return(i);
        }
 
+static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+       {
+       switch(type)
+               {
+       case EVP_CTRL_INIT:
+               data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8;
+               return 1;
+
+       case EVP_CTRL_GET_RC2_KEY_BITS:
+               *(int *)ptr = data(c)->key_bits;
+               return 1;
+                       
+       case EVP_CTRL_SET_RC2_KEY_BITS:
+               if(arg > 0)
+                       {
+                       data(c)->key_bits = arg;
+                       return 1;
+                       }
+               return 0;
+#ifdef PBE_PRF_TEST
+       case EVP_CTRL_PBE_PRF_NID:
+               *(int *)ptr = NID_hmacWithMD5;
+               return 1;
+#endif
+
+       default:
+               return -1;
+               }
+       }
+
 #endif