FIPS low level blocking for AES, RC4 and Camellia. This is complicated by
authorDr. Stephen Henson <steve@openssl.org>
Sun, 5 Jun 2011 17:36:44 +0000 (17:36 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 5 Jun 2011 17:36:44 +0000 (17:36 +0000)
use of assembly language routines: rename the assembly language function
to the private_* variant unconditionally and perform tests from a small
C wrapper.

19 files changed:
apps/speed.c
crypto/aes/aes.h
crypto/aes/aes_core.c
crypto/aes/aes_misc.c
crypto/aes/asm/aes-586.pl
crypto/aes/asm/aes-armv4.pl
crypto/aes/asm/aes-s390x.pl
crypto/aes/asm/aes-x86_64.pl
crypto/camellia/camellia.h
crypto/camellia/cmll_misc.c
crypto/evp/e_rc4.c
crypto/evp/evp_locl.h
crypto/rc4/Makefile
crypto/rc4/asm/rc4-586.pl
crypto/rc4/asm/rc4-s390x.pl
crypto/rc4/asm/rc4-x86_64.pl
crypto/rc4/rc4.h
crypto/rc4/rc4_skey.c
crypto/rc4/rc4_utl.c [new file with mode: 0644]

index 3fee15c5b7389068e31b361a43ccf53b5ff1e2bf..e4e84a5200b47af424a8d8a0f6bff4856b6b84cb 100644 (file)
 #define idea_set_encrypt_key   private_idea_set_encrypt_key
 #define SEED_set_key   private_SEED_set_key
 #define RC2_set_key    private_RC2_set_key
+#define RC4_set_key    private_RC4_set_key
 #define DES_set_key_unchecked  private_DES_set_key_unchecked
+#define AES_set_encrypt_key    private_AES_set_encrypt_key
+#define AES_set_decrypt_key    private_AES_set_decrypt_key
+#define Camellia_set_key       private_Camellia_set_key
 #endif
 
 #ifndef HAVE_FORK
index d2c99730fec5f3d2d6c9675bad5807274f55daca..031abf01b50c37f9207a214c7d65f4f701ce9308 100644 (file)
@@ -90,6 +90,11 @@ int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
        AES_KEY *key);
 
+int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+       AES_KEY *key);
+int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+       AES_KEY *key);
+
 void AES_encrypt(const unsigned char *in, unsigned char *out,
        const AES_KEY *key);
 void AES_decrypt(const unsigned char *in, unsigned char *out,
index a7ec54f4dade256fd6744e8d84bf0c7ca481119e..7d3ecb7325a5f1b7705efaa0988f57f69ab2041c 100644 (file)
@@ -625,7 +625,7 @@ static const u32 rcon[] = {
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
                        AES_KEY *key) {
 
        u32 *rk;
@@ -726,7 +726,7 @@ int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 /**
  * Expand the cipher key into the decryption key schedule.
  */
-int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
                         AES_KEY *key) {
 
         u32 *rk;
index 4fead1b4c7c553b656c5d6eccdb527fdedfbd349..f083488ecb34aa842c7e8637945df1bf4fa72192 100644 (file)
@@ -50,6 +50,7 @@
  */
 
 #include <openssl/opensslv.h>
+#include <openssl/crypto.h>
 #include <openssl/aes.h>
 #include "aes_locl.h"
 
@@ -62,3 +63,23 @@ const char *AES_options(void) {
         return "aes(partial)";
 #endif
 }
+
+/* FIPS wrapper functions to block low level AES calls in FIPS mode */
+
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+                       AES_KEY *key)
+       {
+#ifdef OPENSSL_FIPS
+       fips_cipher_abort(AES);
+#endif
+       return private_AES_set_encrypt_key(userKey, bits, key);
+       }
+
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+                       AES_KEY *key)
+       {
+#ifdef OPENSSL_FIPS
+       fips_cipher_abort(AES);
+#endif
+       return private_AES_set_decrypt_key(userKey, bits, key);
+       }
index aab40e6f1cf206c7b8912829d6beb308982150b9..687ed811be4796639d79841ee11fc882470a9dc9 100755 (executable)
@@ -39,7 +39,7 @@
 # but exhibits up to 10% improvement on other cores.
 #
 # Second version is "monolithic" replacement for aes_core.c, which in
-# addition to AES_[de|en]crypt implements AES_set_[de|en]cryption_key.
+# addition to AES_[de|en]crypt implements private_AES_set_[de|en]cryption_key.
 # This made it possible to implement little-endian variant of the
 # algorithm without modifying the base C code. Motivating factor for
 # the undertaken effort was that it appeared that in tight IA-32
@@ -2854,12 +2854,12 @@ sub enckey()
     &set_label("exit");
 &function_end("_x86_AES_set_encrypt_key");
 
-# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
-&function_begin_B("AES_set_encrypt_key");
+&function_begin_B("private_AES_set_encrypt_key");
        &call   ("_x86_AES_set_encrypt_key");
        &ret    ();
-&function_end_B("AES_set_encrypt_key");
+&function_end_B("private_AES_set_encrypt_key");
 
 sub deckey()
 { my ($i,$key,$tp1,$tp2,$tp4,$tp8) = @_;
@@ -2916,9 +2916,9 @@ sub deckey()
        &mov    (&DWP(4*$i,$key),$tp1);
 }
 
-# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
-&function_begin_B("AES_set_decrypt_key");
+&function_begin_B("private_AES_set_decrypt_key");
        &call   ("_x86_AES_set_encrypt_key");
        &cmp    ("eax",0);
        &je     (&label("proceed"));
@@ -2974,7 +2974,7 @@ sub deckey()
        &jb     (&label("permute"));
 
        &xor    ("eax","eax");                  # return success
-&function_end("AES_set_decrypt_key");
+&function_end("private_AES_set_decrypt_key");
 &asciz("AES for x86, CRYPTOGAMS by <appro\@openssl.org>");
 
 &asm_finish();
index c51ee1fbf63b25f150c7328d80c582f196cf42f8..4c4af4a0bf8df4be52f631b3021542aa191a6c3a 100644 (file)
@@ -20,7 +20,7 @@
 
 # May 2007.
 #
-# AES_set_[en|de]crypt_key is added.
+# private_AES_set_[en|de]crypt_key is added.
 
 # July 2010.
 #
@@ -371,11 +371,11 @@ _armv4_AES_encrypt:
        ldr     pc,[sp],#4              @ pop and return
 .size  _armv4_AES_encrypt,.-_armv4_AES_encrypt
 
-.global AES_set_encrypt_key
-.type   AES_set_encrypt_key,%function
+.global private_AES_set_encrypt_key
+.type   private_AES_set_encrypt_key,%function
 .align 5
-AES_set_encrypt_key:
-       sub     r3,pc,#8                @ AES_set_encrypt_key
+private_AES_set_encrypt_key:
+       sub     r3,pc,#8                @ private_AES_set_encrypt_key
        teq     r0,#0
        moveq   r0,#-1
        beq     .Labrt
@@ -392,7 +392,7 @@ AES_set_encrypt_key:
        bne     .Labrt
 
 .Lok:  stmdb   sp!,{r4-r12,lr}
-       sub     $tbl,r3,#AES_set_encrypt_key-AES_Te-1024        @ Te4
+       sub     $tbl,r3,#private_AES_set_encrypt_key-AES_Te-1024        @ Te4
 
        mov     $rounds,r0              @ inp
        mov     lr,r1                   @ bits
@@ -606,21 +606,21 @@ AES_set_encrypt_key:
 .Labrt:        tst     lr,#1
        moveq   pc,lr                   @ be binary compatible with V4, yet
        bx      lr                      @ interoperable with Thumb ISA:-)
-.size  AES_set_encrypt_key,.-AES_set_encrypt_key
+.size  private_AES_set_encrypt_key,.-private_AES_set_encrypt_key
 
-.global AES_set_decrypt_key
-.type   AES_set_decrypt_key,%function
+.global private_AES_set_decrypt_key
+.type   private_AES_set_decrypt_key,%function
 .align 5
-AES_set_decrypt_key:
+private_AES_set_decrypt_key:
        str     lr,[sp,#-4]!            @ push lr
-       bl      AES_set_encrypt_key
+       bl      private_AES_set_encrypt_key
        teq     r0,#0
        ldrne   lr,[sp],#4              @ pop lr
        bne     .Labrt
 
        stmdb   sp!,{r4-r12}
 
-       ldr     $rounds,[r2,#240]       @ AES_set_encrypt_key preserves r2,
+       ldr     $rounds,[r2,#240]       @ private_AES_set_encrypt_key preserves r2,
        mov     $key,r2                 @ which is AES_KEY *key
        mov     $i1,r2
        add     $i2,r2,$rounds,lsl#4
@@ -696,7 +696,7 @@ $code.=<<___;
        tst     lr,#1
        moveq   pc,lr                   @ be binary compatible with V4, yet
        bx      lr                      @ interoperable with Thumb ISA:-)
-.size  AES_set_decrypt_key,.-AES_set_decrypt_key
+.size  private_AES_set_decrypt_key,.-private_AES_set_decrypt_key
 
 .type  AES_Td,%object
 .align 5
index 7e018892982ced4c99b170ac3641d09d59735bca..c15059cd86e04b7327d87832b76ff7fce876fcef 100644 (file)
@@ -28,7 +28,7 @@
 
 # May 2007.
 #
-# Implement AES_set_[en|de]crypt_key. Key schedule setup is avoided
+# Implement private_AES_set_[en|de]crypt_key. Key schedule setup is avoided
 # for 128-bit keys, if hardware support is detected.
 
 # Januray 2009.
@@ -730,12 +730,12 @@ _s390x_AES_decrypt:
 ___
 
 $code.=<<___;
-# void AES_set_encrypt_key(const unsigned char *in, int bits,
+# void private_AES_set_encrypt_key(const unsigned char *in, int bits,
 #               AES_KEY *key) {
-.globl AES_set_encrypt_key
-.type  AES_set_encrypt_key,\@function
+.globl private_AES_set_encrypt_key
+.type  private_AES_set_encrypt_key,\@function
 .align 16
-AES_set_encrypt_key:
+private_AES_set_encrypt_key:
        lghi    $t0,0
        clgr    $inp,$t0
        je      .Lminus1
@@ -1011,17 +1011,17 @@ $code.=<<___;
 .Lminus1:
        lghi    %r2,-1
        br      $ra
-.size  AES_set_encrypt_key,.-AES_set_encrypt_key
+.size  private_AES_set_encrypt_key,.-private_AES_set_encrypt_key
 
-# void AES_set_decrypt_key(const unsigned char *in, int bits,
+# void private_AES_set_decrypt_key(const unsigned char *in, int bits,
 #               AES_KEY *key) {
-.globl AES_set_decrypt_key
-.type  AES_set_decrypt_key,\@function
+.globl private_AES_set_decrypt_key
+.type  private_AES_set_decrypt_key,\@function
 .align 16
-AES_set_decrypt_key:
-       stg     $key,32($sp)            # I rely on AES_set_encrypt_key to
+private_AES_set_decrypt_key:
+       stg     $key,32($sp)            # I rely on private_AES_set_encrypt_key to
        stg     $ra,112($sp)            # save non-volatile registers!
-       bras    $ra,AES_set_encrypt_key
+       bras    $ra,private_AES_set_encrypt_key
        lg      $key,32($sp)
        lg      $ra,112($sp)
        ltgr    %r2,%r2
@@ -1123,10 +1123,10 @@ $code.=<<___;
        la      $key,4($key)
        brct    $rounds,.Lmix
 
-       lmg     %r6,%r13,48($sp)# as was saved by AES_set_encrypt_key!
+       lmg     %r6,%r13,48($sp)# as was saved by private_AES_set_encrypt_key!
        lghi    %r2,0
        br      $ra
-.size  AES_set_decrypt_key,.-AES_set_decrypt_key
+.size  private_AES_set_decrypt_key,.-private_AES_set_decrypt_key
 ___
 
 #void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
index a545e892aef00c6584c5bf31e1389ee3dc8bbeb1..47307f1b7923e98551338d6fe1c1f69ff5f98568 100755 (executable)
@@ -1277,13 +1277,13 @@ $code.=<<___;
 ___
 }
 
-# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
 $code.=<<___;
-.globl AES_set_encrypt_key
-.type  AES_set_encrypt_key,\@function,3
+.globl private_AES_set_encrypt_key
+.type  private_AES_set_encrypt_key,\@function,3
 .align 16
-AES_set_encrypt_key:
+private_AES_set_encrypt_key:
        push    %rbx
        push    %rbp
        push    %r12                    # redundant, but allows to share 
@@ -1304,7 +1304,7 @@ AES_set_encrypt_key:
        add     \$56,%rsp
 .Lenc_key_epilogue:
        ret
-.size  AES_set_encrypt_key,.-AES_set_encrypt_key
+.size  private_AES_set_encrypt_key,.-private_AES_set_encrypt_key
 
 .type  _x86_64_AES_set_encrypt_key,\@abi-omnipotent
 .align 16
@@ -1547,13 +1547,13 @@ $code.=<<___;
 ___
 }
 
-# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
 $code.=<<___;
-.globl AES_set_decrypt_key
-.type  AES_set_decrypt_key,\@function,3
+.globl private_AES_set_decrypt_key
+.type  private_AES_set_decrypt_key,\@function,3
 .align 16
-AES_set_decrypt_key:
+private_AES_set_decrypt_key:
        push    %rbx
        push    %rbp
        push    %r12
@@ -1622,7 +1622,7 @@ $code.=<<___;
        add     \$56,%rsp
 .Ldec_key_epilogue:
        ret
-.size  AES_set_decrypt_key,.-AES_set_decrypt_key
+.size  private_AES_set_decrypt_key,.-private_AES_set_decrypt_key
 ___
 
 # void AES_cbc_encrypt (const void char *inp, unsigned char *out,
index cf0457dd976f80b9e582266b04d75db35f9d2929..67911e0adf83ac7505cebb13fc46c15cfd440334 100644 (file)
@@ -88,6 +88,10 @@ struct camellia_key_st
        };
 typedef struct camellia_key_st CAMELLIA_KEY;
 
+#ifdef OPENSSL_FIPS
+int private_Camellia_set_key(const unsigned char *userKey, const int bits,
+       CAMELLIA_KEY *key);
+#endif
 int Camellia_set_key(const unsigned char *userKey, const int bits,
        CAMELLIA_KEY *key);
 
index f44689124b4a64e0d682c2d27125a4c177e92043..664583ff5de355be6d3cd979401153ee91069a8b 100644 (file)
@@ -50,6 +50,7 @@
  */
  
 #include <openssl/opensslv.h>
+#include <openssl/crypto.h>
 #include <openssl/camellia.h>
 #include "cmll_locl.h"
 
@@ -57,6 +58,14 @@ const char CAMELLIA_version[]="CAMELLIA" OPENSSL_VERSION_PTEXT;
 
 int Camellia_set_key(const unsigned char *userKey, const int bits,
        CAMELLIA_KEY *key)
+#ifdef OPENSSL_FIPS
+       {
+       fips_cipher_abort(Camellia);
+       return private_Camellia_set_key(userKey, bits, key);
+       }
+int private_Camellia_set_key(const unsigned char *userKey, const int bits,
+       CAMELLIA_KEY *key)
+#endif
        {
        if(!userKey || !key)
                return -1;
index 8b5175e0fdc8a3e79639cb615404c162cc614b86..b4f6bda82d4026ffabbc8d17eb8da76db5600435 100644 (file)
@@ -62,6 +62,7 @@
 #ifndef OPENSSL_NO_RC4
 
 #include <openssl/evp.h>
+#include "evp_locl.h"
 #include <openssl/objects.h>
 #include <openssl/rc4.h>
 
index 0f2aacfb723f412cd111a808980649b21d70f4d2..3f018f756fa06c7235091564ec13b5bca1329ed8 100644 (file)
@@ -363,6 +363,8 @@ void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx);
 #define idea_set_encrypt_key   private_idea_set_encrypt_key
 #define SEED_set_key   private_SEED_set_key
 #define RC2_set_key    private_RC2_set_key
+#define RC4_set_key    private_RC4_set_key
 #define DES_set_key_unchecked  private_DES_set_key_unchecked
+#define Camellia_set_key       private_Camellia_set_key
 
 #endif
index 264451a213f9db1b53a3b4ddd3611042049c236a..8f6b0dc68a022d6b987637f4a79d6dd6fcea9300 100644 (file)
@@ -21,8 +21,8 @@ TEST=rc4test.c
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=rc4_skey.c rc4_enc.c
-LIBOBJ=$(RC4_ENC)
+LIBSRC=rc4_skey.c rc4_enc.c rc4_utl.c
+LIBOBJ=$(RC4_ENC) rc4_utl.o
 
 SRC= $(LIBSRC)
 
index 38a44a70efc2412409c9c450c2448533510dafd1..ec82c35b888f63e32b7ebb9aae6b49cbb4562533 100644 (file)
@@ -24,7 +24,7 @@
 #      For reference! This code delivers ~80% of rc4-amd64.pl
 #      performance on the same Opteron machine.
 # (**) This number requires compressed key schedule set up by
-#      RC4_set_key [see commentary below for further details].
+#      private_RC4_set_key [see commentary below for further details].
 #
 #                                      <appro@fy.chalmers.se>
 
@@ -166,8 +166,8 @@ $idx="edx";
 
 &external_label("OPENSSL_ia32cap_P");
 
-# void RC4_set_key(RC4_KEY *key,int len,const unsigned char *data);
-&function_begin("RC4_set_key");
+# void private_RC4_set_key(RC4_KEY *key,int len,const unsigned char *data);
+&function_begin("private_RC4_set_key");
        &mov    ($out,&wparam(0));              # load key
        &mov    ($idi,&wparam(1));              # load len
        &mov    ($inp,&wparam(2));              # load data
@@ -245,7 +245,7 @@ $idx="edx";
        &xor    ("eax","eax");
        &mov    (&DWP(-8,$out),"eax");          # key->x=0;
        &mov    (&DWP(-4,$out),"eax");          # key->y=0;
-&function_end("RC4_set_key");
+&function_end("private_RC4_set_key");
 
 # const char *RC4_options(void);
 &function_begin_B("RC4_options");
index 96681fa05ec915847036ce1461c8fb0906ad1e59..c7ed59510bafb2ec6c48191b069434330a7332ee 100644 (file)
@@ -130,7 +130,7 @@ $code.=<<___;
 ___
 }
 
-# void RC4_set_key(RC4_KEY *key,unsigned int len,const void *inp)
+# void private_RC4_set_key(RC4_KEY *key,unsigned int len,const void *inp)
 {
 $cnt="%r0";
 $idx="%r1";
@@ -143,10 +143,10 @@ $ikey="%r7";
 $iinp="%r8";
 
 $code.=<<___;
-.globl RC4_set_key
-.type  RC4_set_key,\@function
+.globl private_RC4_set_key
+.type  private_RC4_set_key,\@function
 .align 64
-RC4_set_key:
+private_RC4_set_key:
        stmg    %r6,%r8,48($sp)
        lhi     $cnt,256
        la      $idx,0(%r0)
@@ -182,7 +182,7 @@ RC4_set_key:
 .Ldone:
        lmg     %r6,%r8,48($sp)
        br      $rp
-.size  RC4_set_key,.-RC4_set_key
+.size  private_RC4_set_key,.-private_RC4_set_key
 
 ___
 }
index 677be5fe25badfe44a315855a827c65d71543e72..b04eb1a72ab4c4ac93375da5703b99d24612c3ed 100755 (executable)
@@ -266,10 +266,10 @@ $ido="%r9";
 
 $code.=<<___;
 .extern        OPENSSL_ia32cap_P
-.globl RC4_set_key
-.type  RC4_set_key,\@function,3
+.globl private_RC4_set_key
+.type  private_RC4_set_key,\@function,3
 .align 16
-RC4_set_key:
+private_RC4_set_key:
        lea     8($dat),$dat
        lea     ($inp,$len),$inp
        neg     $len
@@ -339,7 +339,7 @@ RC4_set_key:
        mov     %eax,-8($dat)
        mov     %eax,-4($dat)
        ret
-.size  RC4_set_key,.-RC4_set_key
+.size  private_RC4_set_key,.-private_RC4_set_key
 
 .globl RC4_options
 .type  RC4_options,\@abi-omnipotent
index 29d1acccf59ed7ed74051c5374f90538d9ed4850..88ceb46bc54d11fbc613c049c24c938d6bcfada5 100644 (file)
@@ -79,6 +79,7 @@ typedef struct rc4_key_st
  
 const char *RC4_options(void);
 void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
+void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
 void RC4(RC4_KEY *key, size_t len, const unsigned char *indata,
                unsigned char *outdata);
 
index b22c40b0bd0641c57bdf8b3eab439d9e6fe551d8..d8108cf19cc4c6d7389eb24d2a0bd2f47828c68f 100644 (file)
@@ -85,7 +85,7 @@ const char *RC4_options(void)
  * Date: Wed, 14 Sep 1994 06:35:31 GMT
  */
 
-void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
+void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
        {
         register RC4_INT tmp;
         register int id1,id2;
diff --git a/crypto/rc4/rc4_utl.c b/crypto/rc4/rc4_utl.c
new file mode 100644 (file)
index 0000000..ab3f02f
--- /dev/null
@@ -0,0 +1,62 @@
+/* crypto/rc4/rc4_utl.c -*- mode:C; c-file-style: "eay" -*- */
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
+#include <openssl/rc4.h>
+
+void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
+       {
+#ifdef OPENSSL_FIPS
+       fips_cipher_abort(RC4);
+#endif
+       private_RC4_set_key(key, len, data);
+       }